<?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>Sat, 14 Aug 2010 07:14:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.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>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>0</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;">&gt;</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>3</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>
		<item>
		<title>PyCon Argentina 2009: Abierta la Inscripción</title>
		<link>http://blog.marcelofernandez.info/2009/08/pycon-argentina-2009-abierta-la-inscripcion/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pycon-argentina-2009-abierta-la-inscripcion</link>
		<comments>http://blog.marcelofernandez.info/2009/08/pycon-argentina-2009-abierta-la-inscripcion/#comments</comments>
		<pubDate>Sat, 15 Aug 2009 01:57:58 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=417</guid>
		<description><![CDATA[Sólo me voy a limitar a copiar el texto de la invitación&#8230; de más está decir que espero ansioso los días para ir, y creo que va a estar buenísima. Si sos programador o estás haciendo tus primeras armas en la programación, ¡no podés faltar! Está abierta la inscripción para participar de PyCon Argentina 2009, [...]]]></description>
			<content:encoded><![CDATA[<p>Sólo me voy a limitar a copiar el texto de la invitación&#8230; de más está decir que espero ansioso los días para ir, y creo que va a estar <strong>buenísima</strong>. Si sos programador o estás haciendo tus primeras armas en la programación, ¡no podés faltar!</p>
<p style="text-align: center;"><a href="http://ar.pycon.org"><img class="size-full wp-image-418 aligncenter" title="Banner PyConAR-2009" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/08/PyConAR-2009-banner-grande.png" alt="PyConAR-2009-banner-grande" width="582" height="72" /></a></p>
<blockquote><p>Está abierta la inscripción para participar de PyCon Argentina 2009, la primera conferencia en castellano sobre el lenguaje de programación Python, a realizarse los días 4 y 5 de septiembre en la sede de la <a href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=es&amp;geocode=&amp;q=zabala+1837,+buenos+aires&amp;sll=-34.608418,-58.373161&amp;sspn=0.279182,0.617294&amp;ie=UTF8&amp;ll=-34.562927,-58.444004&amp;spn=0.008729,0.01929&amp;t=h&amp;z=16&amp;iwloc=r0" target="_blank">Universidad de Belgrano, Zabala 1837, en la Ciudad de Buenos Aires</a>.</p>
<p>En esta primera edición contaremos con la participación de Jacob Kaplan-Moss (creador de <a href="http://www.djangoproject.com/" target="_blank">Django</a>) y Collin Winter (core developer de Python) como invitados especiales del evento, y con más de 30 charlas sobre Python y temas relacionados, desde tutoriales para principiantes hasta charlas de nivel avanzado.</p>
<p><strong>Cronograma de charlas: </strong><br />
<a href="http://ar.pycon.org/2009/conference/schedule/">http://ar.pycon.org/2009/conference/schedule/</a></p>
<p><strong>La entrada es libre y gratuita</strong>. Para evitar contratiempos, confirmar su asistencia y recibir credencial y demás materiales de la conferencia, se recomienda realizar inscripción previa en el sitio web.</p>
<p><strong>Inscripción y más información: </strong><br />
<a href="http://ar.pycon.org/2009/registration/">http://ar.pycon.org/2009/registration/</a></p></blockquote>
<p>Espero conocer gente ahí&#8230; ¡nos vemos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/08/pycon-argentina-2009-abierta-la-inscripcion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control de Versiones: Manejando las diferencias entre distribuido y centralizado</title>
		<link>http://blog.marcelofernandez.info/2009/07/control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado</link>
		<comments>http://blog.marcelofernandez.info/2009/07/control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado/#comments</comments>
		<pubDate>Sat, 25 Jul 2009 18:11:41 +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=346</guid>
		<description><![CDATA[Dando vueltas por ahí, me entero que es muy sencillo utilizar localmente versionado de código fuente (gracias a los sistemas de control de versiones distribuidos, como por ejemplo Mercurial, GIT y Bazaar) para luego subir/actualizar los cambios a un repositorio Subversion principal. Es decir, en vez de usar los comandos svn como clientes de un [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-352" title="VCSs" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/VCSs.png" alt="VCSs" width="144" height="149" />Dando vueltas <a href="http://wxwidgets.blogspot.com/2009/07/playing-with-dvcs-for-wxwidgets.html" target="_blank">por ahí</a>, me entero que es muy sencillo utilizar localmente versionado de código fuente (gracias a los sistemas de control de versiones distribuidos, como por ejemplo <a href="http://mercurial.selenic.com/wiki/" target="_blank">Mercurial</a>, <a href="http://git-scm.com/" target="_blank">GIT</a> y <a href="http://bazaar-vcs.org/" target="_blank">Bazaar</a>) para luego subir/actualizar los cambios a un repositorio <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> principal. Es decir, en vez de usar los comandos svn como clientes de un servidor Subversion, es posible utilizar alguno de estos sistemas distribuidos como clientes &#8220;consumidores&#8221; del repositorio principal, para luego aprovechar <a href="http://en.wikipedia.org/wiki/Distributed_revision_control#Advantages" target="_blank">sus importantes ventajas</a> en forma local.</p>
<p>En principio, admito que no conozco ningún <a href="http://en.wikipedia.org/wiki/Revision_control" target="_blank">VCS</a> distribuido, más que nada por vagancia (je), pero esto en particular sí lo necesito de vez en cuando, principalmente cuando no estoy conectado, y/o cuando los cambios que hago con respecto a <em>trunk</em> son profundos, llevan tiempo y quiero tener un control más &#8220;fino&#8221; en lo que hago.</p>
<p>A ver, habiendo nombrado primero los sistemas más conocidos (por mí), se desprende que tenemos:</p>
<ul>
<li><a href="http://mercurial.selenic.com/wiki/" target="_blank"><img class="size-full wp-image-354 alignright" title="Logo Mercurial" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/logo-droplets-200.png" alt="Logo Mercurial" width="98" height="118" /></a><a href="http://bitbucket.org/durin42/hgsubversion/wiki/Home" target="_blank">Mercurial-Svn</a>: Si bien el autor del artículo que me inspiró a escribir esto (<a href="http://www.linkedin.com/pub/vadim-zeitlin/6/145/445" target="_blank">Vadim Zeitlin</a>, desarrollador de <a href="http://www.wxwidgets.org/" target="_blank">wxWidgets</a>) comentaba que le gusta muchísimo Mercurial por su fácil uso, al momento de probar esta extensión para subir los cambios al servidor <a href="http://svn.wxwidgets.org" target="_blank">SVN de wxWidgets</a> tuvo problemas de performance, uso de memoria, etc. De todas maneras, el código fuente en el repositorio de wxWidgets <a href="http://trac.wxwidgets.org/browser" target="_blank">es bastante grandote</a> (~330MB), así que quizás funcione bien para proyectos chicos/medianos, y más si uno ya conoce Mercurial.</li>
</ul>
<ul>
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html" target="_blank">Git-Svn</a>: Bueno, citando nuevamente a Vadim, parece que critica un poco lo complicado de los comandos Git, sin embargo termina recomendándolo en forma rotunda por su velocidad y poca utilización de espacio extra en el disco*. <a href="http://flavio.castelli.name/howto_use_git_with_svn" target="_blank">Acá</a> parece haber un tutorial cortito para utilizarlo (Google me <a href="http://utsl.gen.nz/talks/git-svn/intro.html" target="_blank">devuelve</a> <a href="http://tsunanet.blogspot.com/2007/07/learning-git-svn-in-5min.html" target="_blank">muchísimos</a> <a href="http://git.or.cz/course/svn.html" target="_blank">enlaces</a> <a href="http://xmleye.wordpress.com/2008/10/13/recuperando-repo-svn-desde-clon-git-svn/" target="_blank">más</a> por si es poco).</li>
</ul>
<p style="text-align: center;"><a href="http://git-scm.com/"><img class="aligncenter size-full wp-image-362" title="Git Version Control" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/header.gif" alt="Git Version Control" width="442" height="59" /></a></p>
<ul>
<li><a href="http://bazaar-vcs.org/BzrForeignBranches/Subversion" target="_blank">Bazaar-Svn</a>: A <a href="http://bazaar-vcs.org/" target="_blank">Bazaar</a> lo conozco por su relación estrecha con <a href="http://launchpad.net" target="_blank">Launchpad</a> y <a href="http://www.ubuntu.com" target="_blank">Ubuntu</a>, por lo tanto yo probaría a este primero&#8230; ah, y ellos mismos elaboraron una comparativa (<span style="text-decoration: line-through;">imparcial</span>) entre <a href="http://bazaar-vcs.org/BzrVsGit" target="_blank">Bazaar y Git</a> por un lado, y entre <a href="http://bazaar-vcs.org/BzrVsHg" target="_blank">Bazaar y Mercurial</a> por el otro.</li>
</ul>
<p>En fin, recién me sumerjo en la lectura y experimentación de todo esto, pero para aquellos que trabajan contra un servidor SVN** y suben sus cambios con poca frecuencia al repositorio principal, &#8220;rompiendo todo&#8221; cada vez que lo hacen (guiño, guiño), me parece que esto les viene perfecto.</p>
<p><a href="http://bazaar-vcs.org"><img class="size-full wp-image-371 alignright" title="Bazaar" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/Bazaar1.png" alt="Bazaar" width="221" height="93" /></a>Además, tengo entendido que no es difícil usar Bazaar (por poner uno de ejemplo), y realmente está muy <em>cool</em> poder volver atrás en los cambios que uno hizo desde que hizo el <em>checkout</em>/<em>update</em> del SVN, mientras desarrolla, y sin tener que conectarse a Internet (VPN/SSH/etc.).</p>
<p>(*) Cuando el cliente de control de versiones distribuido hace un <em>checkout</em> del repositorio Subversion, no sólo descarga la última versión de <em>trunk</em>, sino que descarga <strong>todas las versiones pasadas de todas las ramas existentes</strong>, con lo cual el consumo de espacio en disco local pasa a ser un asunto importante. Git, según Vadim, parece tener poco <em>overhead</em> en este sentido comparado con la extensión de Mercurial.</p>
<p>(**) Una de las cuestiones que no le hacen perder valor e importancia a SVN es que, al ser centralizado, sigue siendo relevante en empresas que quieren tener un control más o menos estricto de su código; por lo tanto, la migración a sistemas distribuidos no siempre estará bajo su radar. Es por eso que hablo de &#8220;diferencias&#8221; en el título del post y no de una &#8220;futura migración&#8221;, es decir, <strong>que los distribuidos sean los &#8220;nuevos vecinos de la cuadra&#8221; no quiere decir que vengan a reemplazar a los viejos y conocidos</strong>. <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/07/control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>¡Hola Mundo!</title>
		<link>http://blog.marcelofernandez.info/2009/05/hola-mundo/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=hola-mundo</link>
		<comments>http://blog.marcelofernandez.info/2009/05/hola-mundo/#comments</comments>
		<pubDate>Mon, 25 May 2009 00:36:39 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[misceláneos]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=1</guid>
		<description><![CDATA[Bueno, este es el primer post de mi blog sobre WordPress en dominio propio, marcelofernandez.info. No hace falta cambiar el Feed RSS, ya que al hacerlo yo en FeedBurner, directamente va a levantar los nuevos posts del dominio nuevo. El cambio lo hice estrictamente porque me cansé de esperar que Blogger avance&#8230; es demasiado básico [...]]]></description>
			<content:encoded><![CDATA[<p>Bueno, este es el primer post de mi blog sobre <a href="http://www.wordpress.org">WordPress</a> en dominio propio, <a href="http://marcelofernandez.info">marcelofernandez.info</a>.</p>
<p>No hace falta cambiar el <a href="http://feeds2.feedburner.com/ElBlogDeMarcelo" target="_blank">Feed RSS</a>, ya que al hacerlo yo en <a href="http://www.feedburner.com" target="_blank">FeedBurner</a>, directamente va a levantar los nuevos posts del dominio nuevo.</p>
<p>El cambio lo hice estrictamente porque me cansé de esperar que Blogger avance&#8230; es demasiado básico para un montón de cosas. Vamos a ver cómo nos va, por ahora me enamoré de WordPress. <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/05/hola-mundo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
