<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>El Blog de Marcelo! » python</title>
	
	<link>http://blog.marcelofernandez.info</link>
	<description>Blog Informático sobre Programación, Software Libre y/o Open Source, Linux, Python y alguna que otra cosa más...</description>
	<lastBuildDate>Sun, 08 Apr 2012 04:01:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ElBlogDeMarcelo_python" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="elblogdemarcelo_python" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Jornada de Python en Luján: PyDay Luján 2012</title>
		<link>http://blog.marcelofernandez.info/2012/03/jornada-de-python-en-lujan-pyday-lujan-2012/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=jornada-de-python-en-lujan-pyday-lujan-2012</link>
		<comments>http://blog.marcelofernandez.info/2012/03/jornada-de-python-en-lujan-pyday-lujan-2012/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 13:29:04 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=1148</guid>
		<description><![CDATA[PyAr, el grupo de usuarios de Python Argentina, está orgulloso de presentar una nueva Jornada del lenguaje de programación Python 2012 (PyDay) en la Universidad Nacional de Luján, el día Sábado 5 de Mayo de 2012 de 11Hs a 18Hs. Durante el Python Day se darán pequeños cursos y charlas relacionadas a este lenguaje, creando un espacio [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Página del Evento: PyDay Luján 2012" href="http://www.pyday.com.ar/lujan2012" target="_blank"><img class="alignright size-full wp-image-1154" style="border-style: initial; border-color: initial;" title="python_lujan" src="http://blog.marcelofernandez.info/wp-content/uploads/2012/03/python_lujan.png" alt="PyDay Luján 2012" width="100" height="139" /></a> <a title="PyAr" href="http://www.python.org.ar" target="_blank">PyAr</a>, el grupo de usuarios de Python Argentina, está orgulloso de presentar una nueva Jornada del lenguaje de programación <a title="Lenguaje de Programación Python" href="http://es.wikipedia.org/wiki/Python" target="_blank">Python</a> 2012 (<a title="PyDay Lujan 2012" href="http://www.pyday.com.ar/lujan2012/" target="_blank">PyDay</a>) en la <a title="Universidad Nacional de Luján" href="http://www.unlu.edu.ar" target="_blank">Universidad Nacional de Luján</a>, el día Sábado 5 de Mayo de 2012 de 11Hs a 18Hs.</p>
<p>Durante el Python Day se darán pequeños cursos y charlas relacionadas a este lenguaje, creando un espacio en donde cualquier persona interesada pueda acercarse para preguntar, aprender y experimentar con esta herramienta.</p>
<p>Python es un lenguaje moderno, sencillo de aprender pero muy poderoso en cuanto a la cantidad de aplicaciones en las que es usado profesional y académicamente: en sitios web, en juegos, aplicaciones de escritorio y en scripting en general, etc&#8230;</p>
<p>El publico al que nos dirigimos es de todos los niveles, pero estamos muy interesados en acercar Python a quienes solo lo conocen de oído o directamente no saben de que tipo de lenguaje se trata. Tendremos charlas especiales para ellos.</p>
<p>Con esta misma invitación damos por iniciado el Call For Charlas; aquellos interesados ya pueden proponer nuevas charlas y son bienvenidos los colaboradores y empresas/entidades interesadas en participar y auspiciar la jornada.</p>
<p>Cualquier duda o consulta, puede visitar <a title="PyDay Luján 2012" href="http://www.pyday.com.ar/lujan2012/" target="_blank">la página del evento</a>, o contactarse vía mail a <a href="mailto:pydaylujan@gmail.com">pydaylujan@gmail.com</a>.</p>
<p>El encuentro se llevará a cabo en el pabellón 400 de la sede central de la UNLu (ver página <a title="Cómo llegar a la UNLu" href="http://www.unlux.com.ar/como-llegar/" target="_blank">Cómo Llegar</a>)</p>
<p>La entrada libre y gratuita (previa inscripción web), ¡los esperamos!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2012/03/jornada-de-python-en-lujan-pyday-lujan-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Estableciendo conexiones HTTPS “bien seguras” en Python</title>
		<link>http://blog.marcelofernandez.info/2011/02/estableciendo-conexiones-https-bien-seguras-en-python/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=estableciendo-conexiones-https-bien-seguras-en-python</link>
		<comments>http://blog.marcelofernandez.info/2011/02/estableciendo-conexiones-https-bien-seguras-en-python/#comments</comments>
		<pubDate>Sat, 19 Feb 2011 19:45:55 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=1112</guid>
		<description><![CDATA[Hace unos días que tenía pendiente colgar esto acá, ya que a alguien en PyAr le fue útil. HTTPS es la manera de establecer conexiones HTTP pero seguras, en el sentido de que previo al diálogo HTTP estándar pero luego de establecerse la conexión TCP contra el servidor, se negocia entre los participantes una conexión/sesión [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días que tenía pendiente colgar esto acá, ya que a alguien en <a href="http://www.python.org.ar" target="_blank">PyAr</a> <a href="http://comments.gmane.org/gmane.org.user-groups.python.argentina/44953" target="_blank">le fue útil</a>.</p>
<p><a href="http://es.wikipedia.org/wiki/Https" target="_blank">HTTPS</a> es la manera de establecer conexiones HTTP pero <em>seguras</em>, en el sentido de que previo al diálogo HTTP estándar pero luego de establecerse la conexión TCP contra el servidor, se negocia entre los participantes una conexión/sesión &#8220;especial&#8221; entre ambos.  Allí se intercambian certificados con el fin de autenticar contra quién se &#8220;está hablando&#8221;, para luego, si hubo éxito en la dicha comprobación, encriptar (o no) todo lo que va para el otro lado, tanto del Servidor al Cliente (generalmente un navegador), como del Cliente al Servidor.</p>
<p>Todo eso forma parte de SSL 3.0 (hoy <a href="http://es.wikipedia.org/wiki/Transport_Layer_Security" target="_blank">TLS 1.0</a>), y si bien se puede utilizar para cualquier conexión TCP (SMTP, IMAP, etc., lo pueden usar también), su uso más común se da cuando uno entra a su casilla de Webmail o su cuenta del Banco desde el navegador;  lo que sucede allí es que nuestro navegador autentica al Servidor, y si todo va bien nos muestra el famoso &#8220;candadito&#8221; e informa que la sesión &#8220;es segura&#8221;. Ahora bien, en esos casos, el Banco o Webmail no nos autentica a nosotros como Cliente y deja que cualquiera se conecte a su página, ya que eso requiere varios pasos más (sería realmente engorroso que sea obligatorio).</p>
<p>Sin embargo, en nuestra vida de programadores nos solemos encontrar con necesidades del entorno que nos obliguen a esta situación un tanto extrema y bastante más segura: que tanto el Cliente que desarrollamos autentique al Servidor como que el Servidor autentique al Cliente, amén de que la conexión muy probablemente deberá estar encriptada. <strong>Esto nos permitirá asegurarnos que los Clientes (software) que se conecten a nuestro Servidor sean únicamente quienes queremos que sean</strong> (o casi).</p>
<p>Python, dentro del módulo <a href="http://docs.python.org/library/httplib.html" target="_blank">httplib</a> nos provee de la clase <strong>HTTPSConnection</strong>, que maneja y nos abstrae en varias de estas cuestiones de SSL/TLS y nos deja trabajar a nivel HTTP (una capa más arriba). Lo que hay que observar bien (y que recién en la versión 2.7 de la documentación apareció en rojo), es que esta clase aún cuando uno le puede pasar como parámetro los paths a certificados, <strong>en realidad no hace ninguna comprobación de validez del certificado que el Servidor exporta</strong>. Con lo cual, hay un potencial problema: que nuestro cliente mande los datos a cualquier lado menos a nuestro Servidor de confianza.</p>
<p>¿Y cómo se fuerza a que nuestro programa Cliente chequee el certificado del Servidor? Armé esta clase que extiende sólo lo necesario a HTTPSConnection, que funciona en Python 2.6.x y que me permite hacer eso.</p>
<p>Le agregué un ejemplo en la llamada a __main__ para mostrar cómo se usa:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;">#-*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">socket</span>
<span style="color: #ff7700;font-weight:bold;">import</span> ssl
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> HTTPSClientAuthConnection<span style="color: black;">&#40;</span><span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPSConnection</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Class to make a HTTPS connection, with support for full client-based
        SSL Authentication.
    &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, host, port, key_file, cert_file, ca_file, timeout=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPSConnection</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, host, key_file=key_file,
                                                   cert_file=cert_file<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">key_file</span> = key_file
        <span style="color: #008000;">self</span>.<span style="color: black;">cert_file</span> = cert_file
        <span style="color: #008000;">self</span>.<span style="color: black;">ca_file</span> = ca_file
        <span style="color: #008000;">self</span>.<span style="color: black;">timeout</span> = timeout
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> connect<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Connect to a host on a given (SSL) port.
            If ca_file is pointing somewhere, use it to check Server Certificate.
&nbsp;
            Redefined/copied and extended from httplib.py:1105 (Python 2.6.x).
            This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter
            to ssl.wrap_socket(), which forces SSL to check server certificate
            against our client certificate.
        &quot;&quot;&quot;</span>
        sock = <span style="color: #dc143c;">socket</span>.<span style="color: black;">create_connection</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">host</span>, <span style="color: #008000;">self</span>.<span style="color: black;">port</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">timeout</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>._tunnel_host:
            <span style="color: #008000;">self</span>.<span style="color: black;">sock</span> = sock
            <span style="color: #008000;">self</span>._tunnel<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># If there's no CA File, don't force Server Certificate Check</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">ca_file</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">sock</span> = ssl.<span style="color: black;">wrap_socket</span><span style="color: black;">&#40;</span>sock, <span style="color: #008000;">self</span>.<span style="color: black;">key_file</span>, <span style="color: #008000;">self</span>.<span style="color: black;">cert_file</span>,
                        ca_certs=<span style="color: #008000;">self</span>.<span style="color: black;">ca_file</span>, cert_reqs=ssl.<span style="color: black;">CERT_REQUIRED</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">sock</span> = ssl.<span style="color: black;">wrap_socket</span><span style="color: black;">&#40;</span>sock, <span style="color: #008000;">self</span>.<span style="color: black;">key_file</span>, <span style="color: #008000;">self</span>.<span style="color: black;">cert_file</span>,
                                              cert_reqs=ssl.<span style="color: black;">CERT_NONE</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #808080; font-style: italic;"># Little test-case of our class</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">6</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'usage: ./https_auth_handler.py host port key_file cert_file ca_file'</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        host, port, key_file, cert_file, ca_file = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
    conn = HTTPSClientAuthConnection<span style="color: black;">&#40;</span>host, port, key_file=key_file,
                                           cert_file=cert_file, ca_file=ca_file<span style="color: black;">&#41;</span>
    conn.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'GET'</span>, <span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
    response = conn.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> response.<span style="color: black;">status</span>, response.<span style="color: black;">reason</span>
    data = response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> data
    conn.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>En cuanto a la generación de las claves de Cliente, Servidor y CA <a href="http://www.google.com.ar/search?q=openssl+certificate+client+server+creation" target="_blank">hay unos cuantos artículos</a> y es relativamente sencillo una vez que se entiende qué se está haciendo. Por otra parte que en estos casos es muy común que el Servidor exija que el Cliente si o sí envíe su certificado o sino la conexión se deberá caer; esto en el caso del Servidor Apache está <a href="http://httpd.apache.org/docs/2.2/ssl/ssl_howto.html#allclients" target="_blank">bien documentado</a>.</p>
<p>Entiendo que en Python 3.2 esto está resuelto en la misma API standard de Python (en su momento abrí <a href="http://bugs.python.org/issue3466" target="_blank">un ticket similar</a> para usar esto con urllib2, que incluye cosas importantes como el manejo de cookies, por ejemplo), y comentaron eso.</p>
<p>Según me dijeron en PyAr, es casi seguro que este ejemplo no funcione en Python 2.7, así que en un futuro no muy lejano espero poder adaptar este código a dicha versión y seguramente lo estaré subiendo en esta página.</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2011/02/estableciendo-conexiones-https-bien-seguras-en-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Navegador simple con wxPython + Webkit/GTK</title>
		<link>http://blog.marcelofernandez.info/2010/10/navegador-simple-con-wxpython-webkitgtk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=navegador-simple-con-wxpython-webkitgtk</link>
		<comments>http://blog.marcelofernandez.info/2010/10/navegador-simple-con-wxpython-webkitgtk/#comments</comments>
		<pubDate>Sun, 10 Oct 2010 01:28:54 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=995</guid>
		<description><![CDATA[Hace algunos posts (¡casi un año ya!) escribí sobre una manera fácil y rápida de tener un componente &#8220;navegador web&#8221; en Python sobre Linux/BSD, gracias a PyGTK y WebkitGTK, llamado lógicamente, pyWebkitGTK. En pocas líneas de código uno puede disponer de un navegador potente y completo en un panel de su aplicación basada en PyGTK, [...]]]></description>
			<content:encoded><![CDATA[<p>Hace algunos posts (¡casi un año ya!) <a href="http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/" target="_blank">escribí</a> sobre una manera fácil y rápida de tener un componente &#8220;navegador web&#8221; en Python sobre Linux/BSD, gracias a <a href="http://www.pygtk.org" target="_blank">PyGTK</a> y <a href="http://webkitgtk.org/" target="_blank">WebkitGTK</a>, llamado lógicamente, <a href="http://code.google.com/p/pywebkitgtk/" target="_blank">pyWebkitGTK</a>. En pocas líneas de código uno puede disponer de un navegador potente y completo en un panel de su aplicación basada en <a href="http://www.pygtk.org">PyGTK</a>, ideal para integrar aún más la cada omnipresente Web.</p>
<p>Las vueltas de la vida y las ganas de experimentar y aprender te llevan a probar otros frameworks/librerías, como lo es <a href="http://www.wxpython.org" target="_blank">wxPython</a>; tanto es así que de vez en cuando tengo el placer de dar <a href="http://blog.marcelofernandez.info/charlas/" target="_blank">alguna charla</a> al respecto <a href="#nota1">[1]</a>, y una de las debilidades que le usualmente le encontraba es la falta de un componente &#8220;browser web&#8221; nativo y soportado en todas las plataformas (wxPython sólo incluye IE embebible como ActiveX en Windows).</p>
<p>En búsqueda de alternativas existe <a href="http://wxwebkit.wxcommunity.com/" target="_blank">wxWebKit</a>, pero al proyecto le faltan terminar algunas cosas para tener lista su versión &#8220;1.0&#8243;, y si bien <a href="http://www.kirix.com/labs/wxwebconnect/" target="_blank">wxWebConnect</a> funciona, no da soporte para wxPython, sólo wxWidgets desde C++. Eso nos deja con que en Linux/BSD no tenemos componente que nos dé esta posibildad, pero&#8230; si wxPython en estas plataformas utiliza GTK por debajo, ¿no podríamos usar pyWebkitGTK como componente para embeberlo en nuestra aplicación Python?</p>
<p>La respuesta por suerte es afirmativa, y en una rápida búsqueda en la <a href="http://wiki.wxpython.org" target="_blank">Wiki de wxPython</a> encontré <a href="http://wiki.wxpython.org/wxGTKWebKit" target="_blank">un ejemplo de cómo hacerlo</a>. Si bien podría copiar y pegar la receta, me gustaría &#8220;<em>aggiornarla</em>&#8220; un poquito, al menos traduciendo y explicando un poco más los comentarios.</p>
<p>Primero vamos a mostrar cómo se vería el módulo que incluye un widget HtmlPanel, wxwebkitgtk.py:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># coding:utf-8</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    wxWebkitGTK - Componente wxPython que embebe un navegador
                   utiliza la biblioteca Webkit GTK desde Python (PyWebkitGTK).
&nbsp;
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
    Basado en: http://wiki.wxpython.org/wxGTKWebKit
&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">import</span> gobject
gobject.<span style="color: black;">threads_init</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk, gtk.<span style="color: black;">gdk</span>
<span style="color: #ff7700;font-weight:bold;">import</span> webkit
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> HtmlPanel<span style="color: black;">&#40;</span>wx.<span style="color: black;">Panel</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Panel</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Aquí es donde se hace la &quot;magia&quot; de embeber webkit en wxGTK.</span>
        whdl = <span style="color: #008000;">self</span>.<span style="color: black;">GetHandle</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        window = gtk.<span style="color: black;">gdk</span>.<span style="color: black;">window_lookup</span><span style="color: black;">&#40;</span>whdl<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Debemos mantener la referencia a &quot;pizza&quot;, sino obtenemos un segfault.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pizza</span> = window.<span style="color: black;">get_user_data</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Obtengo el padre de la clase GtkPizza, un gtk.ScrolledWindow</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span> = <span style="color: #008000;">self</span>.<span style="color: black;">pizza</span>.<span style="color: black;">parent</span>
        <span style="color: #808080; font-style: italic;"># Saco el objeto GtkPizza para poner un WebView en su lugar</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>.<span style="color: black;">remove</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pizza</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">webview</span> = webkit.<span style="color: black;">WebView</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">webview</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>.<span style="color: black;">show_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>La &#8220;magia&#8221; consiste en que, sabiendo que pyWebkitGTK necesita un componente <a href="http://library.gnome.org/devel/pygtk/stable/class-gtkscrolledwindow.html" target="_blank">ScrolledWindow</a> GTK como padre para funcionar correctamente, se utiliza la biblioteca PyGTK para buscar el ScrolledWindow GTK donde está embebido el wx.Panel de la clase (su &#8220;abuelo&#8221;), y reemplazar el hijo GTKPizza (un componente inventado por wxWidgets para funcionar) por el WebView de Webkit.</p>
<p>Aquí hay un ejemplo de cómo se puede utilizar este panel como widget de wxPython completo e independiente, copiando la funcionalidad básica del <a href="http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/">post de PyWebkitGTK</a>, el archivo wxwebkitgtk_demo.py:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># coding: utf-8</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    wxSimpleBrowser - Navegador muy muy simple de internet, sólo de ejemplo,
                      que utiliza la biblioteca Webkit GTK desde wxPython.
&nbsp;
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">from</span> wxwebkitgtk <span style="color: #ff7700;font-weight:bold;">import</span> HtmlPanel
&nbsp;
DEFAULT_URL = <span style="color: #483d8b;">'http://www.python.org'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> wxSimpleBrowser<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">TxtUrl</span> = wx.<span style="color: black;">TextCtrl</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, wx.<span style="color: black;">ID_ANY</span>, style=wx.<span style="color: black;">TE_PROCESS_ENTER</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">TxtUrl</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_TEXT_ENTER</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnTxtURL</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Box</span> = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">VERTICAL</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Box</span>.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">TxtUrl</span>, proportion=<span style="color: #ff4500;">0</span>, flag=wx.<span style="color: black;">EXPAND</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetSizer</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">Box</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetSize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>,<span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Necesitamos tener mostrado el componente padre del Panel para que funcione,</span>
        <span style="color: #808080; font-style: italic;"># por eso mostramos primero el Frame y después creamos el HtmlPanel</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">HtmlPanel</span> = HtmlPanel<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Box</span>.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">HtmlPanel</span>, proportion=<span style="color: #ff4500;">1</span>, flag=wx.<span style="color: black;">EXPAND</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SendSizeEvent</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Para acomodar el panel al tamaño del frame</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnTxtURL<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">Open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">TxtUrl</span>.<span style="color: black;">GetValue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> Open<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Podemos acceder a todos los métods del objeto WebView</span>
        <span style="color: #808080; font-style: italic;"># http://webkitgtk.org/reference/webkitgtk-webkitwebview.html</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">HtmlPanel</span>.<span style="color: black;">webview</span>.<span style="color: black;">load_uri</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">TxtUrl</span>.<span style="color: black;">SetValue</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetTitle</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'wxSimpleBrowser - %s'</span> <span style="color: #66cc66;">%</span> url<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">1</span>:
        url = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        url = DEFAULT_URL
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    browser = wxSimpleBrowser<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    browser.<span style="color: black;">Open</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Creo que para la enorme funcionalidad que nos brinda el proceso de ponerlo en práctica es bastante simple, y aunque depende de PyGTK, ésta biblioteca hoy está disponible &#8220;de fábrica&#8221; en cualquier distribución moderna de GNU/Linux. </p>
<p>De aquí en más es ser muy sencillo dejar al lector el armado de un widget para wxPython que en Windows muestre el componente navegador de IE y en Linux un navegador Webkit.</p>
<p><a name="nota1"></a>[1] ¡La semana que viene voy a estar en la <a href="http://ar.pycon.org/2010/about/" target="_blank">PyCon Argentina 2010</a> dando una charla de <a href="http://ar.pycon.org/2010/conference/schedule/event/55/" target="_blank">Introducción a wxPython</a>! <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> </p>
<p>¡Saludos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/10/navegador-simple-con-wxpython-webkitgtk/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PyDay Rafaela 2010 – Introducción a wxPython</title>
		<link>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pyday-rafaela-2010-introduccion-a-wxpython</link>
		<comments>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/#comments</comments>
		<pubDate>Mon, 10 May 2010 17:32:48 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=687</guid>
		<description><![CDATA[Para no ser menos que Juanjo y Fisa, ¡qué bueno estuvo el PyDay Rafaela 2010! Muchos (muchos) asistentes, muy buena onda, y una chorizeada + fernet a la noche inolvidables&#8230; En la sección de Charlas del blog están los slides de mi &#8220;Introducción a wxPython&#8221;, más los ejemplos de rigor. También hice propaganda de Ubuntu [...]]]></description>
			<content:encoded><![CDATA[<p>Para no ser menos que <a href="http://www.juanjoconti.com.ar/2010/05/09/charla-entendiendo-decoradores-en-python/" target="_blank">Juanjo</a> y <a href="http://fisadev.blogspot.com/2010/05/pyday-rafaela-2010_09.html" target="_blank">Fisa</a>, ¡qué bueno estuvo el <a href="www.pyday.com.ar/rafaela2010/" target="_blank">PyDay Rafaela 2010</a>!</p>
<p>Muchos (muchos) asistentes, muy buena onda, y una chorizeada + fernet a la noche inolvidables&#8230; En la sección de <a href="http://blog.marcelofernandez.info/charlas/">Charlas</a> del blog están los <a href="http://marcelofernandez.info/charlas/Introduccion%20a%20wxPython.pdf">slides</a> de mi &#8220;Introducción a wxPython&#8221;, más los <a href="http://marcelofernandez.info/charlas/Introduccion%20a%20wxPython.zip">ejemplos</a> de rigor. También <a href="http://marcelofernandez.info/charlas/Ubuntu Lightning Talk.pdf">hice propaganda</a> de Ubuntu en las Lightning Talks. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<p>Acá hay un par de fotos&#8230; con los días van a ir apareciendo más cosas en el sito del evento&#8230; incluso los videos de las charlas. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<a href='http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/attachment/08052010022/' title='PyDay Rafaela 2010'><img width="150" height="150" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/05/08052010022-150x150.jpg" class="attachment-thumbnail" alt="PyDay Rafaela 2010" title="PyDay Rafaela 2010" /></a>
<a href='http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/attachment/023/' title='PyDay Rafaela 2010 - Grupo completo'><img width="150" height="150" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/05/023-150x150.jpg" class="attachment-thumbnail" alt="PyDay Rafaela 2010 - Grupo completo" title="PyDay Rafaela 2010 - Grupo completo" /></a>

<p><strong>Actualización</strong>: <a href="http://pydayrafaela.blip.tv/" target="_blank">Acá</a> están los videos de las charlas.</p>
<p>Gracias a los chicos de PyRafaela por la organización, dedicación y aguante&#8230;. ¡espero que se repita!</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Renderizando PDFs en Python con Poppler II</title>
		<link>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=renderizando-pdfs-en-python-con-poppler-ii</link>
		<comments>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 18:04:29 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=663</guid>
		<description><![CDATA[Hace unos días me llegó un mail de alguien preguntándome cómo, a partir de la parte I de este artículo, hacer un sencillo visor de PDFs con wxPython. Me encontré con algunas dificultades, principalmente que el ScrolledWindow de wxPython no permite actualizarse dinámicamente, o automáticamente según el contenido (esto sí es bastante sencillo en GTK); [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días me llegó un mail de alguien preguntándome cómo, a partir de la <a href="http://blog.marcelofernandez.info/2009/05/renderizando-pdfs-en-python-con-poppler/" target="_self">parte I de este artículo</a>, hacer un sencillo visor de PDFs con <a href="http://www.wxpython.org" target="_blank">wxPython</a>. Me encontré con algunas dificultades, principalmente que el <a href="www.wxpython.org/docs/api/wx.ScrolledWindow-class.html" target="_blank">ScrolledWindow</a> de wxPython no permite actualizarse dinámicamente, o automáticamente según el contenido (esto <a href="http://www.pygtk.org/docs/pygtk/class-gtkadjustment.html" target="_blank">sí es bastante sencillo en GTK</a>); con lo cual se complicaba hacer zoom, modificar el tamaño de la ventana y adaptar los scrollbars, etc.</p>
<p>Sin embargo, con alguna vuelta de más pude armar un ejemplo, que paso a dejar <a href="http://code.activestate.com/recipes/577195-wxpython-pdf-viewer-using-poppler/" target="_blank">acá</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># coding: utf-8</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    wxPDFViewer - Simple PDF Viewer using Python-Poppler and wxPython 
    Marcelo Fidel Fernandez - MIT License
    http://www.marcelofernandez.info - marcelo.fidel.fernandez@gmail.com
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">import</span> wx.<span style="color: black;">lib</span>.<span style="color: black;">wxcairo</span> <span style="color: #ff7700;font-weight:bold;">as</span> wxcairo
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> poppler
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> PDFWindow<span style="color: black;">&#40;</span>wx.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; This example class implements a PDF Viewer Window, handling Zoom and Scrolling &quot;&quot;&quot;</span>
&nbsp;
    MAX_SCALE = <span style="color: #ff4500;">2</span>
    MIN_SCALE = <span style="color: #ff4500;">1</span>
    SCROLLBAR_UNITS = <span style="color: #ff4500;">20</span>  <span style="color: #808080; font-style: italic;"># pixels per scrollbar unit</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">ScrolledWindow</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent, wx.<span style="color: black;">ID_ANY</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Wrap a panel inside</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span> = wx.<span style="color: black;">Panel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Initialize variables</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> = <span style="color: #ff4500;">0</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> = <span style="color: #ff4500;">1</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">document</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">None</span>
        <span style="color: #808080; font-style: italic;"># Connect panel events</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_PAINT</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnPaint</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_KEY_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnKeyDown</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_LEFT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnLeftDown</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_RIGHT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnRightDown</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> LoadDocument<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">file</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">document</span> = poppler.<span style="color: black;">document_new_from_file</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;file://&quot;</span> + <span style="color: #008000;">file</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_n_pages</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_page</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">n_page</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span>.<span style="color: black;">get_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
        <span style="color: #008000;">self</span>._UpdateSize<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnPaint<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        dc = wx.<span style="color: black;">PaintDC</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">panel</span><span style="color: black;">&#41;</span>
        cr = wxcairo.<span style="color: black;">ContextFromDC</span><span style="color: black;">&#40;</span>dc<span style="color: black;">&#41;</span>
        cr.<span style="color: black;">set_source_rgb</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># White background</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">1</span>:
            cr.<span style="color: black;">scale</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span>, <span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>
        cr.<span style="color: black;">rectangle</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: black;">&#41;</span>
        cr.<span style="color: black;">fill</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span>.<span style="color: black;">render</span><span style="color: black;">&#40;</span>cr<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnLeftDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span> + <span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnRightDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span> - <span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, new_scale<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> new_scale <span style="color: #66cc66;">&gt;</span>= PDFWindow.<span style="color: black;">MIN_SCALE</span> <span style="color: #ff7700;font-weight:bold;">and</span> new_scale <span style="color: #66cc66;">&lt;</span>= PDFWindow.<span style="color: black;">MAX_SCALE</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> = new_scale
            <span style="color: #808080; font-style: italic;"># Obtain the current scroll position</span>
            prev_position = <span style="color: #008000;">self</span>.<span style="color: black;">GetViewStart</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Scroll to the beginning because I'm going to redraw all the panel</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Scroll</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Redraw (calls OnPaint and such)</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Update panel Size and scrollbar config</span>
            <span style="color: #008000;">self</span>._UpdateSize<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># Get to the previous scroll position</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Scroll</span><span style="color: black;">&#40;</span>prev_position<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, prev_position<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _UpdateSize<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        u = PDFWindow.<span style="color: black;">SCROLLBAR_UNITS</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">SetSize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetScrollbars</span><span style="color: black;">&#40;</span>u, u, <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>/u, <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>/u<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnKeyDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        update = <span style="color: #008000;">True</span>
        <span style="color: #808080; font-style: italic;"># More keycodes in http://docs.wxwidgets.org/stable/wx_keycodes.html#keycodes</span>
        keycode = event.<span style="color: black;">GetKeyCode</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
        <span style="color: #ff7700;font-weight:bold;">if</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span>wx.<span style="color: black;">WXK_PAGEDOWN</span>, wx.<span style="color: black;">WXK_SPACE</span><span style="color: black;">&#41;</span>:
            next_page = <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> + <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> keycode == wx.<span style="color: black;">WXK_PAGEUP</span>:
            next_page = <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> - <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            update = <span style="color: #008000;">False</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> update <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span>next_page <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span>next_page <span style="color: #66cc66;">&lt;</span> <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span><span style="color: black;">&#41;</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> = next_page
                <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_page</span><span style="color: black;">&#40;</span>next_page<span style="color: black;">&#41;</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MyFrame<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, -<span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;wxPdf Viewer&quot;</span>, size=<span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>,<span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span> = PDFWindow<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span>.<span style="color: black;">LoadDocument</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span>.<span style="color: black;">SetFocus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># To capture keyboard events</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__==<span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f = MyFrame<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si bien tengo entendido que el scroll no es &#8220;óptimo&#8221;, ya que en cada OnPaint() se redibuja todo el PDF, anda bastante bien en mi instalación y no parece ser un problema. Lógicamente sí se puede redibujar un área en particular con Cairo (sería la que queda &#8220;invalidada&#8221; por el scroll), pero wxPython me explotó al intentar algunas cosas por un lado, y me parece que en realidad no sé hacerlo bien por el otro (si alguien puede tirar una soga en esto en particular, bienvenido sea).</p>
<p>Me entretuve mucho haciendo esto, y espero que a alguien le sea de utilidad; y aunque todavía Python-Poppler no está disponible para Windows en forma binaria (pero puede ser compilado, <a href="https://bugs.launchpad.net/poppler-python/+bug/499592" target="_blank">bug acá</a>), sí se puede usar en cualquier Linux, OSX, etc. Y nuevamente, hay una <a href="http://bazaar.launchpad.net/~poppler-python/poppler-python/trunk/annotate/head:/demo/demo-poppler.py">demo</a> para hacer esto mismo con PyGTK, y la <a href="http://cgit.freedesktop.org/poppler/poppler/tree/glib/demo" target="_blank">demo de Poppler en C</a> es mucho más completa, además de fácil de leer y traducir a Python.</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Reemplazando texto con expresiones regulares en Python</title>
		<link>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=reemplazando-texto-con-expresiones-regulares-en-python</link>
		<comments>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 18:01:11 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=601</guid>
		<description><![CDATA[Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo &#8220;%s/cosa/otra/g&#8221; del vim nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en PyFpdf, y vi que había algunos archivos .py llenos de llamadas a la función chr(). Claro, PyFpdf es [...]]]></description>
			<content:encoded><![CDATA[<p>Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo &#8220;%s/cosa/otra/g&#8221; <a href="http://www.linux.com/learn/tutorials/8255-vim-tips-the-basics-of-search-and-replace" target="_blank">del vim</a> nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en <a href="http://www.sistemasagiles.com.ar/trac/wiki/PyFpdf" target="_blank">PyFpdf</a>, y vi que había <a href="http://www.sistemasagiles.com.ar/trac/browser/pyfpdf/font/times.py?rev=103" target="_blank">algunos archivos .py</a> llenos de llamadas a la función <a href="http://docs.python.org/library/functions.html#chr" target="_blank">chr()</a>.</p>
<p>Claro, PyFpdf es un port más o menos &#8220;haragán&#8221; (<em>lazy</em>) de <a href="http://www.fpdf.org/" target="_blank">Fpdf para PHP</a>, y el autor original evidentemente encontró más sencillo definir algunas fuentes (en binario) haciendo sucesivas llamadas a la función chr(), como  esta:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">fpdf_charwidths<span style="color: black;">&#91;</span><span style="color: #483d8b;">'times'</span><span style="color: black;">&#93;</span>=<span style="color: black;">&#123;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>,<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Sigue...</span></pre></div></div>

<p>Enseguida pensé en mejorarlo, reemplazando esas sucesivas llamadas a chr() por la misma función pero ya evaluada y en forma de byte string; por ejemplo, la idea era convertir lo anterior en:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">fpdf_charwidths<span style="color: black;">&#91;</span><span style="color: #483d8b;">'times'</span><span style="color: black;">&#93;</span>=<span style="color: black;">&#123;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>01'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>02'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>03'</span>:<span style="color: #ff4500;">250</span>,<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Sigue...</span></pre></div></div>

<p>De esa manera, los archivos .py se simplificarían (se harían más legibles), no sufrirían modificaciones en su comportamiento y hasta serían más veloces en su interpretación y ejecución.</p>
<p>Primero se me ocurrió primero hacer algo más &#8220;a mano&#8221;, pero en cuanto se me complicó un poquito enseguida pensé que la mejor herramienta era usar <a href="http://es.wikipedia.org/wiki/Expresiones_regulares" target="_blank">expresiones regulares</a> para el matching del patrón &#8220;chr(x)&#8221; y, por consiguiente, el <a href="http://docs.python.org/library/re.html" target="_blank">módulo re</a> de la librería estándar de Python.</p>
<p>Leyendo <a href="http://www.amk.ca/python/howto/regex/" target="_blank">esta excelente página</a> y la documentación del módulo en cuestión, armé un script, y me quedó así:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># coding:utf-8</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># This script tries to identify all chr(XX) constant calls in python scripts</span>
<span style="color: #808080; font-style: italic;"># and replace them with '\xXX' strings.</span>
<span style="color: #808080; font-style: italic;"># Author: Marcelo Fernández - License: MIT</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> chrrepl<span style="color: black;">&#40;</span>match<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># See http://www.amk.ca/python/howto/regex/regex.html</span>
    <span style="color: #808080; font-style: italic;"># Use the captured group to get the hex string value.</span>
    char_number = match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>char_number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">3</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Usage: python chr_cleaner.py infile.py outfile.py'</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
    infile = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    outfile = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># Open file for reading</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        fin = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>infile, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
        fout = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>outfile, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Error when reading %s or trying to write %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>infile, outfile<span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    intext = fin.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    pattern = <span style="color: #483d8b;">'chr<span style="color: #000099; font-weight: bold;">\\</span>((<span style="color: #000099; font-weight: bold;">\\</span>d+)<span style="color: #000099; font-weight: bold;">\\</span>)'</span> <span style="color: #808080; font-style: italic;"># Group the chr() function parameter to capture it</span>
    p = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>pattern<span style="color: black;">&#41;</span>
    outtext = p.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>chrrepl, intext<span style="color: black;">&#41;</span>
    fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span>outtext<span style="color: black;">&#41;</span>
    fout.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    fin.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    fout.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si bien creo que el <em>snippet</em> es bastante legible, lo interesante es que con el módulo re se puede:</p>
<ul>
<li><strong>Identificar un patrón en un texto</strong>: En este caso el patrón sería &#8220;chr(\d)&#8221; (\d porque busco un número allí).</li>
<li><strong>Marcar grupos en ese patrón utilizarlos luego</strong>; como sé que voy a utilizar el número en cuestión para convertirlo a su byte string, lo defino dentro de un grupo. El patrón queda entonces &#8220;chr((\d))&#8221;. También es posible usar <em>named groups</em>, identificables por nombre en vez de por posición, pero eso lo dejo de tarea al lector <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </li>
<li><strong>Reemplazar todo el texto que coincide con ese patrón, y en cada reemplazo, llamar a una función que especifique &#8220;lo que hay que poner&#8221; allí, devolviendo un string</strong>. Esta es la frutilla del postre&#8230; <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Si bien puedo usar p.sub() para reemplazar lo que busco por un texto constante, también puedo hacer que en cada ocurrencia del patrón una función cualquiera sea llamada, y  se le pase la instancia de <a href="http://docs.python.org/library/re.html#re.MatchObject" target="_blank">MatchObject</a> para que decidamos qué hacer con lo encontrado y devolver un string. Esto hace la función chrrepl() del snippet. Allí tomo el primer grupo (el grupo 0 es el string completo, el 1 es el primer grupo definido posicionalmente, y así sucesivamente), lo convierto a entero, ejecuto la función chr() y devuelvo su representación en byte string.</li>
</ul>
<p>En fin, después de experimentar un buen rato, esto funcionó y <a href="http://www.sistemasagiles.com.ar/trac/changeset/104/pyfpdf/" target="_blank">acá se puede ver</a> el diff del commit correspondiente para que se aprecie un poco mejor&#8230;</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Navegador simple con Python + Webkit/GTK</title>
		<link>http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=navegador-simple-con-pywebkitgtk</link>
		<comments>http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 21:56:12 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=501</guid>
		<description><![CDATA[Hoy me encontré con otro un hilo en la lista de PyAr que me deja un link más que interesante: ¡Existe un binding para usar Webkit sobre GTK desde Python, y lo mejor de todo es que ya está incluido en los repositorios de Ubuntu 9.10! Webkit es un motor de renderizado (&#8220;dibujado&#8221;) de páginas [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy me encontré con otro <a href="http://mx.grulic.org.ar/lurker/message/20091118.001651.3f9b4974.es.html">un hilo en la lista de PyAr</a> que me deja un link más que interesante: ¡Existe un binding para usar <a href="http://code.google.com/p/pywebkitgtk/">Webkit sobre GTK desde Python</a>, y lo mejor de todo es que <a href="http://packages.ubuntu.com/karmic/python-webkit">ya está incluido en los repositorios</a> de Ubuntu 9.10!</p>
<p><a href="http://www.webkit.org">Webkit</a> es un motor de <a href="http://es.wikipedia.org/wiki/Renderización">renderizado</a> (&#8220;dibujado&#8221;) de páginas web, que es utilizado en el corazón en cada vez más navegadores, como <a href="http://www.google.com.ar/chrome">Chrome</a>, <a href="http://www.apple.com/es/safari/">Safari</a>, <a href="http://www.konqueror.org/">Konqueror</a>, etc. Es super completo y veloz; y permite ejecutarse en muchísimas plataformas y sistemas diferentes.  Si bien existen otros métodos para embeber un navegador en una aplicación PyGTK, como por ejemplo <a href="http://www.pygtk.org/pygtkmozembed/class-gtkmozembed.html">gtkmozembed</a> (que embebe el motor de <a href="http://www.mozilla-europe.org/es/firefox/">Firefox</a>), éste no es muy poderoso, o por lo menos no deja meterle mucha &#8220;mano&#8221; para personalizarlo, y uno termina teniendo relativamente muy poco &#8220;poder&#8221;. En cambio con Webkit/GTK se pueden hacer muchas más cosas, tan sólo hace falta ver la documentación y un ejemplo (links al final, claro). <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>No podía dejar de probarlo. Entonces me puse manos a la obra, y salió esto, tratando de imitar lo que se posteó en la lista:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    SimpleBrowser - Navegador muy muy simple de internet, sólo de ejemplo,
                    que utiliza la biblioteca Webkit GTK desde Python (PyWebkitGTK).
&nbsp;
    Marcelo Fidel Fernández - http://www.marcelofernandez.info 
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk
<span style="color: #ff7700;font-weight:bold;">import</span> webkit
&nbsp;
DEFAULT_URL = <span style="color: #483d8b;">'http://www.python.org'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SimpleBrowser:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span> = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_position</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WIN_POS_CENTER_ALWAYS</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'delete_event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">close_application</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_default_size</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>, <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span>
&nbsp;
        vbox = gtk.<span style="color: black;">VBox</span><span style="color: black;">&#40;</span>spacing=<span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        vbox.<span style="color: black;">set_border_width</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span> = gtk.<span style="color: black;">Entry</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'activate'</span>, <span style="color: #008000;">self</span>._txt_url_activate<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span> = gtk.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">webview</span> = webkit.<span style="color: black;">WebView</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">webview</span><span style="color: black;">&#41;</span>
&nbsp;
        vbox.<span style="color: black;">pack_start</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span>, fill=<span style="color: #008000;">False</span>, expand=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
        vbox.<span style="color: black;">pack_start</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>, fill=<span style="color: #008000;">True</span>, expand=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span>vbox<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _txt_url_activate<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, entry<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._load<span style="color: black;">&#40;</span>entry.<span style="color: black;">get_text</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _load<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">webview</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span>.<span style="color: black;">set_text</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_title</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SimpleBrowser - %s'</span> <span style="color: #66cc66;">%</span> url<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>._load<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> show<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">show_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close_application<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event, data=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">1</span>:
        url = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        url = DEFAULT_URL
&nbsp;
    <span style="color: #808080; font-style: italic;"># PyWebkitGTK necesita habilitar el soporte de los hilos en PyGTK</span>
    gtk.<span style="color: black;">gdk</span>.<span style="color: black;">threads_init</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    browser = SimpleBrowser<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    browser.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    browser.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p style="text-align: left;">¡Y Listo!</p>
<p><a href="http://blog.marcelofernandez.info/wp-content/uploads/2009/11/Pantallazo.png"><img class="size-medium wp-image-504 alignright" title="Pantallazo_PyWebkitGTK" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/11/Pantallazo-300x233.png" alt="Pantallazo_PyWebkitGTK" width="300" height="233" /></a></p>
<p>Todo lo que se necesita en Ubuntu 9.10 para poder correr esto es instalar el paquete &#8220;python-webkit&#8221;; sin embargo, esta versión es la 1.1.5, mientras que PyWebkitGTK va por la 1.1.7 y Webkit/GTK va por la 1.1.15, así que todavía hay lugar para mejoras.</p>
<p>Aquí dejo algunos links:</p>
<ul>
<li><a href="http://code.google.com/p/pywebkitgtk/">PyWebkitGTK</a> se llama el proyecto de llevar <a href="http://webkitgtk.org/">Webkit/GTK</a> (escrito naturalmente en C) a Python.</li>
<li><a href="http://code.google.com/p/pywebkitgtk/source/browse/trunk/demos/browser.py">Acá hay un ejemplo</a> muchísimo más completo de un navegador con múltiples pestañas y todo.</li>
<li>Lamentablemente, la documentación de la biblioteca en Python no existe aún (es un ticket del proyecto), así que por ahora habrá que conformarse con <a href="http://webkitgtk.org/reference/index.html">la documentación de Webkit/GTK</a>; sin embargo, yo lo encuentro bastante legible, ya que enseguida uno se adapta a &#8220;traducir&#8221; cómo se llamaría un método en C a uno en Python.</li>
</ul>
<p>Espero que les sirva. Me divertí mucho haciéndolo. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Visor de Imágenes Simple con PyGTK</title>
		<link>http://blog.marcelofernandez.info/2009/11/visor-de-imagenes-simple-con-pygtk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=visor-de-imagenes-simple-con-pygtk</link>
		<comments>http://blog.marcelofernandez.info/2009/11/visor-de-imagenes-simple-con-pygtk/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 15:00:57 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=472</guid>
		<description><![CDATA[Dado que alguien me pidió vía twitter un ejemplo de cómo hacer un zoom de una imagen en PyGTK, hice este ejemplito sencillo que sólo carga una imagen en un widget Gtk.Image. Maneja el movimiento de la imagen con el mouse, las teclas del cursor y hace zoom con F1 (&#8220;0 o adaptar a ventana&#8221;), [...]]]></description>
			<content:encoded><![CDATA[<p>Dado que alguien me pidió vía twitter un ejemplo de cómo hacer un zoom de una imagen en PyGTK, hice este ejemplito sencillo que sólo carga una imagen en un widget Gtk.Image. </p>
<p>Maneja el movimiento de la imagen con el mouse, las teclas del cursor y hace zoom con F1 (&#8220;0 o adaptar a ventana&#8221;), F2 (+25%), F3 (+50%), F4(+75%) y F5(&#8220;%+100 o 1:1&#8243;).</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    SimpleImageViewer - Visor simple de imágenes, de ejemplo, que utiliza PyGTK.
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
&nbsp;
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
&nbsp;
    TODO: 
        * Dar la opción de usar el scroll del mouse para hacer zoom.
        * Mejorar el código y peformance (quizás).
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> pygtk
pygtk.<span style="color: black;">require</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'2.0'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Variables globales para el ejemplo; podrían ir en un archivo de configuración, </span>
<span style="color: #808080; font-style: italic;"># como por ejemplo 'config.py' e importarlo.</span>
<span style="color: #808080; font-style: italic;"># Mapeo de teclas - Ver constantes en el modulo gtk.keysyms</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk.<span style="color: black;">keysyms</span> <span style="color: #ff7700;font-weight:bold;">as</span> kb
&nbsp;
<span style="color: #808080; font-style: italic;"># Estructura: teclas (en mayúscula, contempla minúsculas también)</span>
<span style="color: #808080; font-style: italic;"># (offset_X_pixeles, offset_Y_pixeles)</span>
OFFSET_GRAL = <span style="color: #ff4500;">50</span>
MOVE_KEYS = <span style="color: black;">&#123;</span> kb.<span style="color: black;">Up</span> : <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, -OFFSET_GRAL<span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># Arriba</span>
              kb.<span style="color: black;">Down</span> : <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,  OFFSET_GRAL<span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># Abajo</span>
              kb.<span style="color: black;">Right</span> : <span style="color: black;">&#40;</span>OFFSET_GRAL, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,  <span style="color: #808080; font-style: italic;"># Derecha</span>
              kb.<span style="color: black;">Left</span> : <span style="color: black;">&#40;</span>-OFFSET_GRAL, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># Izquierda</span>
            <span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Estructura: tecla: nivel de zoom (zoom_ratio)</span>
ZOOM_KEYS = <span style="color: black;">&#123;</span> kb.<span style="color: black;">F1</span>: <span style="color: #ff4500;">0.0</span>,
              kb.<span style="color: black;">F2</span>: <span style="color: #ff4500;">25.0</span>,
              kb.<span style="color: black;">F3</span>: <span style="color: #ff4500;">50.0</span>,
              kb.<span style="color: black;">F4</span>: <span style="color: #ff4500;">75.0</span>,
              kb.<span style="color: black;">F5</span>: <span style="color: #ff4500;">100.0</span>,
            <span style="color: black;">&#125;</span>
&nbsp;
DEFAULT_IMAGE = <span style="color: #483d8b;">'/usr/share/backgrounds/Cherries.jpg'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SimpleImageViewer:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, image_file<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span> = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;delete_event&quot;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">close_application</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_position</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WIN_POS_CENTER_ALWAYS</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_default_size</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>, <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span> = gtk.<span style="color: black;">gdk</span>.<span style="color: black;">pixbuf_new_from_file</span><span style="color: black;">&#40;</span>image_file<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span> = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span>.<span style="color: black;">get_width</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span> = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span>.<span style="color: black;">get_height</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span> = gtk.<span style="color: black;">Image</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span>.<span style="color: black;">set_from_pixbuf</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span> = gtk.<span style="color: black;">Viewport</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># No están por defecto, los agrego</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">add_events</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON_RELEASE_MASK</span> | gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON1_MOTION_MASK</span><span style="color: black;">&#41;</span> 
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-press-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_button_pressed</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-release-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_button_released</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'motion-notify-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_mouse_moved</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Lo conecto a la ventana, ya que siempre tiene el foco</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'key-press-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_key_press</span><span style="color: black;">&#41;</span> 
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">image</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_wnd</span> = gtk.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_wnd</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">viewport</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scrolled_wnd</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">show_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _update_image<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, zoom_ratio<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Updates the image in the widget according to the zoom_ratio
            Actualiza la imagen en el widget Image con el zoom_ratio de parámetro 
        &quot;&quot;&quot;</span>
        <span style="color: #808080; font-style: italic;"># TODO: Prioriza que encaje el ancho por sobre el alto de la imagen </span>
        <span style="color: #808080; font-style: italic;"># al estar maximizado. Mejorar.</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Obtengo las dimensiones actuales del viewport</span>
        rect = <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">get_allocation</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Resize de la imagen conservando las proporciones de la imagen</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span>:
            base = <span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span> - rect.<span style="color: black;">width</span>
            ancho = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">width</span> + <span style="color: black;">&#40;</span>base <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>zoom_ratio/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            relacion = <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>/<span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span>
            alto = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>ancho <span style="color: #66cc66;">*</span> relacion/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            base = <span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span> - rect.<span style="color: black;">height</span>
            alto = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">height</span> + <span style="color: black;">&#40;</span>base <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>zoom_ratio/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            relacion = <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>/<span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span>
            ancho = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>alto <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>relacion/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        scaled_buf = <span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span>.<span style="color: black;">scale_simple</span><span style="color: black;">&#40;</span>ancho, alto, gtk.<span style="color: black;">gdk</span>.<span style="color: black;">INTERP_BILINEAR</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span>.<span style="color: black;">set_from_pixbuf</span><span style="color: black;">&#40;</span>scaled_buf<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _move_image<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, offset_x, offset_y<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Moves the image inside the viewport to the specified offset (+ or - pixels)
            Mueve/Desplaza la imagen del viewport según el offset que se le especifique 
        &quot;&quot;&quot;</span>
        vport = <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>
        xadjust = vport.<span style="color: black;">props</span>.<span style="color: black;">hadjustment</span>
        newx = xadjust.<span style="color: black;">value</span> + offset_x
        yadjust = vport.<span style="color: black;">props</span>.<span style="color: black;">vadjustment</span>
        newy = yadjust.<span style="color: black;">value</span> + offset_y
        <span style="color: #808080; font-style: italic;"># Si las cosas están dentro de los bordes, seteo</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>newx <span style="color: #66cc66;">&gt;</span>= xadjust.<span style="color: black;">lower</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> \
               <span style="color: black;">&#40;</span>newx <span style="color: #66cc66;">&lt;</span>= <span style="color: black;">&#40;</span>xadjust.<span style="color: black;">upper</span> - xadjust.<span style="color: black;">page_size</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            xadjust.<span style="color: black;">value</span> = newx
            vport.<span style="color: black;">set_hadjustment</span><span style="color: black;">&#40;</span>xadjust<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>newy <span style="color: #66cc66;">&gt;</span>= yadjust.<span style="color: black;">lower</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> \
               <span style="color: black;">&#40;</span>newy <span style="color: #66cc66;">&lt;</span>= <span style="color: black;">&#40;</span>yadjust.<span style="color: black;">upper</span> - yadjust.<span style="color: black;">page_size</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            yadjust.<span style="color: black;">value</span> = newy
            vport.<span style="color: black;">set_vadjustment</span><span style="color: black;">&#40;</span>yadjust<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_key_press<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Callback to handle the keys pressed in the main window
            Callback que maneja las teclas que se presionan en la ventana
        &quot;&quot;&quot;</span>
        keycode = gtk.<span style="color: black;">gdk</span>.<span style="color: black;">keyval_to_upper</span><span style="color: black;">&#40;</span>event.<span style="color: black;">keyval</span><span style="color: black;">&#41;</span>
        newx = newy = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> MOVE_KEYS.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            offset_x, offset_y = MOVE_KEYS<span style="color: black;">&#91;</span>keycode<span style="color: black;">&#93;</span>
            <span style="color: #008000;">self</span>._move_image<span style="color: black;">&#40;</span>offset_x, offset_y<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> ZOOM_KEYS.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #008000;">self</span>._update_image<span style="color: black;">&#40;</span>ZOOM_KEYS<span style="color: black;">&#91;</span>keycode<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span> <span style="color: #808080; font-style: italic;"># Con True cancelo el evento</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_mouse_moved<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Callback to the mouse movement inside the viewport
            Callback que es llamado cuando el mouse se mueve en el viewport 
        &quot;&quot;&quot;</span>
        <span style="color: #808080; font-style: italic;"># Ver: http://www.pygtk.org/pygtk2tutorial-es/sec-EventHandling.html</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">is_hint</span>:
            x, y, state = event.<span style="color: black;">window</span>.<span style="color: black;">get_pointer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            state = event.<span style="color: black;">state</span>
        x, y = event.<span style="color: black;">x_root</span>, event.<span style="color: black;">y_root</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> state <span style="color: #66cc66;">&amp;</span> gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON1_MASK</span>:
            offset_x = <span style="color: #008000;">self</span>.<span style="color: black;">prevmousex</span> - x
            offset_y = <span style="color: #008000;">self</span>.<span style="color: black;">prevmousey</span> - y
            <span style="color: #008000;">self</span>._move_image<span style="color: black;">&#40;</span>offset_x, offset_y<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">prevmousex</span> = x
        <span style="color: #008000;">self</span>.<span style="color: black;">prevmousey</span> = y
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_button_pressed<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; When the user presses the left mouse button, save the x and y pixel positions,
            and change the cursor.
            Cuando el usuario presiona el botón izquierdo, guardo los puntos x, y de 
            origen del evento y cambio el cursor a &quot;moviéndose&quot;.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">button</span> == <span style="color: #ff4500;">1</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">change_vport_cursor</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">Cursor</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">FLEUR</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">prevmousex</span> = event.<span style="color: black;">x_root</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">prevmousey</span> = event.<span style="color: black;">y_root</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_button_released<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; When the user releases the left mouse button, set the normal cursor.
            Cuando el usuario suelta el botón izquierdo, vuelvo el cursor al normal &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">button</span> == <span style="color: #ff4500;">1</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">change_vport_cursor</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> change_vport_cursor<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">type</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">window</span>.<span style="color: black;">set_cursor</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close_application<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event, data=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
        image_file = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        image_file = DEFAULT_IMAGE
    SimpleImageViewer<span style="color: black;">&#40;</span>image_file<span style="color: black;">&#41;</span>
    gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Queda pendiente manejar el scroll del mouse para hacer zoom (ya que GTK mueve el gtk.Scrollwindow que contiene la imagen por defecto). Si bien funciona copiando y pegando esto en un archivo, también pueden descargar el ejemplo <a href="http://www.marcelofernandez.info/files/image_viewer.py">desde acá</a>.</p>
<p>Espero que le sirva a alguien. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>Actualización</strong>: ¡Gracias StyXman por <a href="http://grulicueva.homelinux.net/~mdione/glob/posts/our-man-in-toulon/">la comparativa con PyQT</a>! Ahí agregué la licencia y sobre el código&#8230; bueno, sólo agregar que es un ejemplo, la idea era hacer el código verborrágico apropósito. Por otra parte, y como conclusión personal, veo que QT tiene una clase <a href="http://doc.trolltech.com/4.2/qgraphicsview.html">QGraphicsView</a> que maneja solito el tema del arrastrar y mover la imagen (eso lleva unas cuantas líneas en GTK). <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/11/visor-de-imagenes-simple-con-pygtk/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PyCon Argentina 2009, Cappuccino y LLVM</title>
		<link>http://blog.marcelofernandez.info/2009/09/pycon-argentina-2009-cappuccino-y-llvm/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pycon-argentina-2009-cappuccino-y-llvm</link>
		<comments>http://blog.marcelofernandez.info/2009/09/pycon-argentina-2009-cappuccino-y-llvm/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 05:41:36 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=433</guid>
		<description><![CDATA[Me gustaría hacer un post bien largo acerca de todo lo que me dejó personalmente la última PyCon Argentina, pero lamentablemente estoy complicado con el tiempo, ya que no sólo quiero leer y escribir acerca de todo el &#8220;bombardeo&#8221; de información que te deja cada charla, sino que también quisiera investigar un poco cada cosa [...]]]></description>
			<content:encoded><![CDATA[<p>Me gustaría hacer un post bien largo acerca de todo lo que me dejó personalmente la última <a href="http://ar.pycon.org/2009/about/" target="_blank">PyCon Argentina</a>, pero lamentablemente estoy complicado con el tiempo, ya que no sólo quiero leer y escribir acerca de todo el &#8220;bombardeo&#8221; de información que te deja cada charla, sino que también quisiera investigar un poco cada cosa y dejar acá algo más que solamente los links. Pero bueno, vamos a hacer el intento de resaltar lo primero que me viene a la mente.</p>
<h3>Cappuccino y la Web que se viene<a href="http://cappuccino.org"><img class="alignright size-thumbnail wp-image-455" title="Cappuccino Framework" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/09/cappuccino-icon-150x150.png" alt="cappuccino-icon" width="135" height="135" /></a></h3>
<p><span style="background-color: #ffffff;">Uno de los muy interesantes punteros que me dejó la conferencia tiene que ver con las keynotes[1][2], y la existencia por un lado de la aplicación web <a href="http://280slides.com/" target="_blank">280Slides</a> y por el otro del framework en el cual se basa, <a href="http://cappuccino.org/" target="_blank">Cappuccino</a>. Sugiero pegarle una mirada, más que nada a las <a href="http://cappuccino.org/learn/demos/" target="_blank">demos</a> (para los faltos de tiempo como yo); me parece que es <strong>sencillamente genial,</strong> hay mucha influencia del <a href="http://www.apple.com/es/macosx/" target="_blank">OS X</a> acá, y se nota. <strong>Es una aplicación donde la línea entre lo desktop y web se esfuma, literal y definitivamente</strong>. Lástima que hay que aprender oootro lenguaje nuevo, <a href="http://cappuccino.org/learn/" target="_blank">Objective-J</a>.</span></p>
<p><span style="background-color: #ffffff;">Y esto parece que no se va a detener, tal como dijo <a href="http://jacobian.org/" target="_blank">Jacob</a>. Más si nos enteramos que hay <a href="http://games.slashdot.org/story/09/09/13/1820230/Initial-WebGL-Support-Lands-In-WebKit" target="_blank">desarrollos bastante avanzados</a> para integrar contextos canvas 3D en los navegadores, y leemos algunas características futuras de <a href="http://en.wikipedia.org/wiki/HTML_5#New_APIs" target="_blank">HTML5</a>. En resumen, <strong>él plantea que toda la </strong><em><strong>toolchain web</strong></em><strong> actualmente </strong><em><strong>apesta</strong></em><strong>, incluso Python</strong>, y propone algunas líneas de solución para que Python sea <em>el</em> lenguaje web del 2020, cuando HTML 5 sea el estándar y el navegador web sea <a href="http://www.infoworld.com/d/developer-world/are-operating-systems-doomed-086" target="_blank">el nuevo Sistema Operativo</a>. <a href="http://blog.marcelofernandez.info/2009/03/novedades-en-firefox-31-beta-sera-35/" target="_blank">Ya había escrito</a> algo de esto.</span></p>
<h3>Código más rápido, código más optimizado: LLVM<a href="http://www.llvm.org"><img class="alignright size-full wp-image-456" title="LLVM Compiler Infrastructure Project" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/09/DragonSmall.png" alt="DragonSmall" width="136" height="136" /></a></h3>
<p>De la segunda plenaria, me quedó claro que al fin surgió un contendiente de relativa importancia al venerable <a href="http://gcc.gnu.org/" target="_blank">GCC</a>, y se llama <a href="http://llvm.org/" target="_blank">LLVM</a>. Acá tengo más todavía para investigar, pero básicamente el <em>branch</em> <em>performante</em> de Python llamado <a href="http://code.google.com/p/unladen-swallow/" target="_blank">Unladen Swallow</a> implementará (entre varias cosas más) un <a href="http://es.wikipedia.org/wiki/Compilación_en_tiempo_de_ejecución" target="_blank">JIT</a> para <a href="http://en.wikipedia.org/wiki/Python_(programming_language)#CPython" target="_blank">CPython</a> implementado por medio de LLVM; algo así como <a href="http://code.google.com/p/v8/" target="_blank">V8</a> o <a href="https://wiki.mozilla.org/JavaScript:TraceMonkey" target="_blank">TraceMonkey</a> son para Javascript. Una de las cosas en las que Collin afirmó varias veces fue que &#8220;no pretendemos ser originales, queremos robar ideas de cualquier paper, de donde sea, con tal de hacer Python más rápido&#8221; <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Lo malo es que al parecer, y si bien <a href="http://code.google.com/p/unladen-swallow/wiki/ProjectPlan#2009_Q3_and_Beyond" target="_blank">era una de las ideas iniciales del proyecto</a>, eliminar el <a href="http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock" target="_blank">GIL</a> no será tan fácil <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  (de paso y relacionado, ¡excelente charla la de <a href="http://ar.pycon.org/2009/conference/schedule/event/16/" target="_blank">Multiprocesamiento en Python</a>!).</p>
<p>LLVM está haciendo muchos <a href="http://llvm.org/ProjectsWithLLVM/" target="_blank">méritos para ser considerado</a>, como por ejemplo que <a href="http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/9" target="_blank">Apple está apostando muy fuertemente por él</a>, incluso tiene la idea de reemplazarlo definitivamente dejando atrás a GCC. En Snow Leopard (OS X 10.6), ya mismo se ofrece una interfaz compatible con GCC para LLVM además de toda la <em>toolchain</em> para compilar software desde los fuentes con él. FreeBSD <a href="http://barrapunto.com/articles/09/05/12/216239.shtml" target="_blank">también está trabajando para migrar a él</a>. Y si bien todavía le falta bastante camino por recorrer (tiene <a href="http://clang.llvm.org/cxx_status.html" target="_blank">escaso soporte para C++</a>, o que no compila el kernel de Linux, por ejemplo), ya se pueden ver algunas <a href="http://www.phoronix.com/scan.php?page=article&amp;item=apple_llvm_gcc&amp;num=1" target="_blank">muestras de su potencial</a>, y personalmente encontré varios <a href="http://cliffhacks.blogspot.com/2007/03/experimenting-with-llvm.html" target="_blank">comentarios</a> de que es mucho más sencillo contribuir y entender el código del proyecto comparado con GCC.</p>
<p>En fin, repetí en ambos párrafos, en asuntos totalmente diferentes, la palabra <em>toolchain</em>, que significa literalmente &#8220;cadena de herramientas&#8221;, y está relacionado generalmente al uso de varias herramientas como un conjunto en las diferentes etapas de la creación de aplicaciones. Evidentemente, tanto en el mundo de las aplicaciones web, como en el de los lenguajes de programación, se está yendo hacia la optimización de los recursos que tenemos. ¡Buenísimo! <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> </p>
<p>[1] <a href="http://jacobian.org/writing/snakes-on-the-web/" target="_blank">Snakes on the Web &#8211; Jacob Kaplan-Moss</a><br />
[2] <a href="http://ar.pycon.org/2009/conference/schedule/event/35/" target="_blank">Unladen Swallow &#8211; Collin Winter</a></p>
<p>¡Gracias a <a href="http://www.python.com.ar" target="_blank">PyAr</a> por una excelente PyCon!<br />
Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/09/pycon-argentina-2009-cappuccino-y-llvm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desensamblando Python</title>
		<link>http://blog.marcelofernandez.info/2009/08/desensamblando-python/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=desensamblando-python</link>
		<comments>http://blog.marcelofernandez.info/2009/08/desensamblando-python/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 17:53:25 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=429</guid>
		<description><![CDATA[Mucho no me gusta hacer posts con casi nada de aporte propio, pero en este caso se lo merece. Este post sólo va a referenciar al excelente sitio de Doug Hellman, PyMOTW (Python Module of the Week). Básicamente el autor presenta una vez por semana un módulo de la biblioteca estándar de Python, realizando un [...]]]></description>
			<content:encoded><![CDATA[<p>Mucho no me gusta hacer posts con casi nada de aporte propio, pero en este caso se lo merece. Este post sólo va a referenciar al excelente sitio de <a href="http://www.doughellmann.com/about/" target="_blank">Doug Hellman</a>, <a href="http://www.doughellmann.com/PyMOTW/" target="_blank">PyMOTW</a> (Python Module of the Week). Básicamente el autor presenta una vez por semana un módulo de la biblioteca estándar de Python, realizando un análisis del mismo y mostrando ejemplos de uso.</p>
<p>En particular, <a href="http://www.doughellmann.com/PyMOTW/dis/" target="_blank">esta semana</a> hizo una introducción al módulo <a href="http://docs.python.org/library/dis.html" target="_blank">dis</a>, que desensambla código Python mostrando el bytecode respectivo. Lo bueno es que muestra varios usos para el mismo (nuevos para mí), como en el caso de un debug o en el de optimizar el funcionamiento ahorrando bytecodes.</p>
<p>En fin, preparándome para la inminente <a href="http://ar.pycon.org/2009/about/" target="_blank">PyCon Argentina</a>, me entusiasmé leyendo y probando los ejemplos de este post. No puede haber programador python que no esté subscripto a su feed. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/08/desensamblando-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

