<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Codigo Manso</title>
	<atom:link href="http://www.codigomanso.com/es/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.codigomanso.com</link>
	<description>Programación, informática y tecnología</description>
	<lastBuildDate>Fri, 30 Jul 2010 17:19:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Truco Manso: formatear con ceros al principio de un número en javascript</title>
		<link>http://www.codigomanso.com/es/2010/07/simple-javascript-formatting-zero-padding/</link>
		<comments>http://www.codigomanso.com/es/2010/07/simple-javascript-formatting-zero-padding/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 17:08:33 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[formatting]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[padding]]></category>
		<category><![CDATA[truco manso]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=907</guid>
		<description><![CDATA[Hasta ayer echaba en falta un método sencillo y legible para rellenar con ceros cualquier número o cadena en javascript.
Un ejemplo típico es cuando quieres mostrar la hora y quieres que el formato sea hh:mm. No hay ningún problema cuando son las 12:40, pero si es la una y cinco, se muestra 1:5 en vez [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Hasta ayer echaba en falta un método sencillo y legible para rellenar con ceros cualquier número o cadena en javascript.</p>
<p style="text-align: justify;">Un ejemplo típico es cuando quieres mostrar la hora y quieres que el formato sea hh:mm. No hay ningún problema cuando son las 12:40, pero si es la una y cinco, se muestra 1:5 en vez de 01:05. Lo mismo pasa con las fechas y en innumerables situaciones.</p>
<p style="text-align: justify;">Ayer me he encontré una solución que me parece la mejor que he visto hasta la fecha.</p>
<p style="text-align: justify;">Normalmente, tratándose de un cero, uno haría algo como:</p>
<pre><code>h = (h &lt; 10) ? ("0" + h) : h;</code></pre>
<p style="text-align: justify;">Esto no es feo del todo, pero tampoco es elegante. Y que pasa si queremos 3 ceros? Podríamos hacer algo como:</p>
<pre><code>h = (h &lt; 100) ? ( (h &gt;= 10) ? ("0" + h) : ("00" + h) ) : h;</code></pre>
<p style="text-align: justify;">Este código en un if/else seguro que queda más claro, pero aún así esto es una guarrada. Lo normal sería hacerse una función que rellene con ceros (o con cualquier otro caracter), y usar esa función.</p>
<p style="text-align: justify;">Una vez vista la solución más típica y feucha, es el momento de ver la solución mágica:</p>
<pre><code>("0" + h).slice (-2);  // devolverá "01" si h=1; "12" si h=12
("00" + h).slice (-3); // "001" si h=1; "012" si h=12;"123" si h = 123</code></pre>
<p style="text-align: justify;">Lo que hace el código de arriba es concatenar &#8220;00&#8243; con el número (por ejemplo &#8220;00&#8243; + 12 = &#8220;0012&#8243;) y luego cogemos los 3 últimos caracteres empezando desde el final (de ahí el -3). Y los 3 últimos caracteres son: &#8220;012&#8243;</p>
<p style="text-align: justify;">No se a vosotros, pero yo cuando vi esta solución se me iluminó el cielo. ¡¡Que fácil!!</p>
<p style="text-align: justify;">Por cierto, también se puede usar para rellenar con espacios o con lo que se quiera.</p>
<p>Fuentes:</p>
<ul>
<li><a href="http://gugod.org/2007/09/padding-zero-in-javascript.html">Padding zero in Javascript</a></li>
<li><a href="http://dev.enekoalonso.com/2010/07/20/little-tricks-string-padding-in-javascript/">Little tricks: string padding in Javascript</a> en el blog de Eneko Alonso</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/07/simple-javascript-formatting-zero-padding/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Obtener el user-agent en Google App Engine con Python</title>
		<link>http://www.codigomanso.com/es/2010/07/how-to-get-user-agent-in-google-app-engine-with-python/</link>
		<comments>http://www.codigomanso.com/es/2010/07/how-to-get-user-agent-in-google-app-engine-with-python/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 17:23:18 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[user-anget]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=902</guid>
		<description><![CDATA[Básicamente el User-Agent nos indica cual es el cliente que está realizando la petición. Si se trata de un navegador, de un robot, &#8230;  En principio esta cadena se envía en todas las cabeceras HTTP, sea el cliente que sea (aunque también podría omitirse).
Para obtener el &#8220;user-agent&#8221; en Google App Engine símplemente, desde cualquier método [...]]]></description>
			<content:encoded><![CDATA[<p>Básicamente el User-Agent nos indica cual es el cliente que está realizando la petición. Si se trata de un navegador, de un robot, &#8230;  En principio esta cadena se envía en todas las cabeceras HTTP, sea el cliente que sea (aunque también podría omitirse).</p>
<p>Para obtener el &#8220;user-agent&#8221; en Google App Engine símplemente, desde cualquier método &#8220;get&#8221; o &#8220;post&#8221; que derive de <em>webapp.RequestHandler</em> podemos hacer:</p>
<p><strong>self.request.headers['User-Agent']</strong></p>
<p>Otra cosa bastante útil es averiguar la IP del cliente que nos está realizando la petición. Esto es más fácil aún:</p>
<p><strong>self.request.remote_addr</strong></p>
<p>La IP<strong> </strong>se suele utilizar <a href="http://www.codigomanso.com/es/2010/05/geoip-en-google-app-engine/">para localizar geográficamente</a> a la persona que está solicitando la página web.<strong><br />
</strong></p>
<p>Links relacionados:</p>
<ul>
<li><a href="http://www.codigomanso.com/es/2010/05/geoip-en-google-app-engine/#content">Geolocalización  en Google App Engine</a></li>
<li><a href="http://code.google.com/appengine/docs/python/tools/webapp/requestclass.html">Google App Engine &gt; Python &gt; The Request Class</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/07/how-to-get-user-agent-in-google-app-engine-with-python/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Longitud máxima de una URL (o GET) en Google App Engine</title>
		<link>http://www.codigomanso.com/es/2010/06/longitud-maxima-de-una-url-o-get-en-google-app-engine/</link>
		<comments>http://www.codigomanso.com/es/2010/06/longitud-maxima-de-una-url-o-get-en-google-app-engine/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 08:37:40 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[experiment]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[url]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=894</guid>
		<description><![CDATA[Quería realizar experimentos acerca de la longitud máxima con la que se puede hacer una petición con GET en los distintos navegadores, y al final el más restrictivo ha resultado ser el servidor.
Según las pruebas que he estado realizando, resulta que Google App Engine sólo hacepta URLs de hasta 2048 caracteres.
Por lo tanto, si vas [...]]]></description>
			<content:encoded><![CDATA[<p>Quería realizar experimentos acerca de la longitud máxima con la que se puede hacer una petición con GET en los distintos navegadores, y al final el más restrictivo ha resultado ser el servidor.</p>
<p>Según las pruebas que he estado realizando, resulta que Google App Engine sólo hacepta URLs de hasta 2048 caracteres.</p>
<p>Por lo tanto, si vas a realizar una petición GET a tu aplicación en Google App Engine, asegurate de que tanto la dirección de la página, junto con los datos GET no supere los 2048 bytes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/06/longitud-maxima-de-una-url-o-get-en-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>GeoIP en Google App Engine</title>
		<link>http://www.codigomanso.com/es/2010/05/geoip-en-google-app-engine/</link>
		<comments>http://www.codigomanso.com/es/2010/05/geoip-en-google-app-engine/#comments</comments>
		<pubDate>Sat, 29 May 2010 07:34:45 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[geoip]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=885</guid>
		<description><![CDATA[Me resulta sorprendente que Google no ofrezca ningún servicio o método en Google App Engine para obtener la localización geográfica a partir de la IP. Es algo que ellos tienen más que resuelto, y no veo motivo por el cual no lo ofrezcan a los desarrolladores en la parte del servidor  (en la parte del [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Me resulta sorprendente que Google no ofrezca ningún servicio o método en Google App Engine para obtener la localización geográfica a partir de la IP. Es algo que ellos tienen más que resuelto, y no veo motivo por el cual no lo ofrezcan a los desarrolladores en la parte del servidor  (en la parte del cliente se puede usar <a href="http://code.google.com/apis/ajax/documentation/#ClientLocation" target="_blank">google.loader.ClientLocation en javascript</a>)</p>
<p style="text-align: justify;">Por suerte, este es un problema que se puede resolver fácilmente de dos maneras distintas.</p>
<h5 style="text-align: justify;">Solución 1: haciendo peticiones a otro servidor</h5>
<p style="text-align: justify;">Hacer peticiones HTTP a <a href="http://geoip.wtanaka.com/">http://geoip.wtanaka.com/</a> y éste nos devolverá el código de país:</p>
<p style="text-align: justify;">Por ejemplo para saber el país de la dirección 72.14.235.121 sólo habría que hacer una petición a <a href="http://geoip.wtanaka.com/cc/72.14.235.121"><code>http://geoip.wtanaka.com/cc/72.14.235.121</code></a></p>
<p style="text-align: justify;">Para código sobre cómo hacer este tipo de peticiones, podeis echarle un vistazo a <a href="http://code.google.com/p/geo-ip-location/wiki/GoogleAppEngine">http://code.google.com/p/geo-ip-location/wiki/GoogleAppEngine</a></p>
<h5 style="text-align: justify;">Solución 2: implementarlo en el propio servidor</h5>
<p style="text-align: justify;">A mi esta otra solución me gusta más. Se trata símplemente de bajarse la última versión de <a rel="nofollow" href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz">GeoIP.dat</a> y usarla con la librería <a href="http://python-geoip.googlecode.com/svn/trunk/pygeoip.py">pygeoip.py</a></p>
<p style="text-align: justify;">Luego es tan fácil como hacer:</p>
<pre><code>def getCountryByIP (remote_addr):
  GEOIP = pygeoip.Database('GeoIP.dat')
  info = GEOIP.lookup(remote_addr)
  return info.country</code></pre>
<p style="text-align: justify;">Nótese que la librería no está pensada para hacer esto así, ya que cada vez que se llama a <strong>pygeoip.Database</strong> se carga el archivo entero a una cadena en memoria, y, en principio, a nosotros nos interesaría cargarlo sólo una única vez.</p>
<p style="text-align: justify;">Por otra parte, en mi caso sólo me interesaba hacer un único lookup, así que cargar el archivo a memoria no tenía mucho sentido.</p>
<p style="text-align: justify;">He actualizado la librería para permitir dos modos. El modo cargarlo a memoria (mejor si vas a hacer cientos de lookups), y el modo acceder directamente al archivo en disco (mejor si vas a hacer pocos lookups, ya que consume menos memoria y tarda igual o incluso menos).</p>
<p style="text-align: justify;">Aquí os dejo el archivo <a href="http://www.codigomanso.com/archives/python/pygeoip/pygeoip.txt">pygeoip.py</a> con mis cambios. Para usarlo he añadido la función <strong>disk_lookup</strong>:</p>
<p><code>pygeoip.disk_lookup (remote_addr)</code></p>
<p style="text-align: justify;">Para hacer un único lookup va más rápido y consume infinitamente menos memoria.</p>
<p style="text-align: justify;">Desde aquí quiero felicitar a David Wilson, el autor de esta librería, porque ha sido muy fácil implementar estos cambios (por supuesto le he mandado un e-mail, ahora es cosa suya incluir mis cambios o no hacerlo).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/05/geoip-en-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Una de python: force_unicode</title>
		<link>http://www.codigomanso.com/es/2010/05/una-de-python-force_unicode/</link>
		<comments>http://www.codigomanso.com/es/2010/05/una-de-python-force_unicode/#comments</comments>
		<pubDate>Thu, 20 May 2010 19:15:16 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[character encoding]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[force_unicode]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[utf-8]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=880</guid>
		<description><![CDATA[Las codificaciones de caracteres (character encoding) son la mayor patraña jamás inventada, gracias a dios se inventó Unicode, con sus variantes UTF-8 y UTF-32.
Para mi, UTF-8 es, y debería ser el estándar  para guardar o enviar cadenas de texto.
Los lenguajes de programación, python incluido, no deberían soportar otra cosa que no fuera UTF-8 o cadenas [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Las codificaciones de caracteres (character encoding) son la mayor patraña jamás inventada, gracias a dios se inventó Unicode, con sus variantes UTF-8 y UTF-32.</p>
<p style="text-align: justify;">Para mi, UTF-8 es, y debería ser el estándar  para guardar o enviar cadenas de texto.</p>
<p style="text-align: justify;">Los lenguajes de programación, python incluido, no deberían soportar otra cosa que no fuera UTF-8 o cadenas de bytes.  La verdad es que lo voy a dejar aquí, porque cada vez que pienso en este tema, me enciendo.</p>
<p style="text-align: justify;">El caso es que el soporte de codificaciones de texto en Python me parece lo peor. ¿Por qué? Porque no es suficientemente inteligente para mezclar cosas, y lanza excepciones a la mínima.</p>
<p style="text-align: justify;">Hasta hoy, usaba str.decode(&#8216;utf-8&#8242;, &#8216;ignore&#8217;) donde str es la cadena que quiero convertir a UTF-8, pero ni siquiera esto me libraba de excepciones.</p>
<p style="text-align: justify;">Hoy, buscando otra vez una solución, he encontrado la función force_unicode del frámework django. De momento, con las pruebas que he hecho, se lo come todo. Es perfecto.</p>
<p style="text-align: justify;">Símplemente quería compartir esto:</p>
<pre><code>def force_unicode(s, encoding='utf-8', errors='ignore'):
    """
    Returns a unicode object representing 's'. Treats bytestrings using the
    'encoding' codec.
    """
    import codecs
    if s is None:
      return ''

    try:
        if not isinstance(s, basestring,):
            if hasattr(s, '__unicode__'):
                s = unicode(s)
            else:
                try:
                    s = unicode(str(s), encoding, errors)
                except UnicodeEncodeError:
                    if not isinstance(s, Exception):
                        raise
                    # If we get to here, the caller has passed in an Exception
                    # subclass populated with non-ASCII data without special
                    # handling to display as a string. We need to handle this
                    # without raising a further exception. We do an
                    # approximation to what the Exception's standard str()
                    # output should be.
                    s = ' '.join([force_unicode(arg, encoding, errors) for arg in s])
        elif not isinstance(s, unicode):
            # Note: We use .decode() here, instead of unicode(s, encoding,
            # errors), so that if s is a SafeString, it ends up being a
            # SafeUnicode at the end.
            s = s.decode(encoding, errors)
    except UnicodeDecodeError, e:
        if not isinstance(s, Exception):
            raise UnicodeDecodeError (s, *e.args)
        else:
            # If we get to here, the caller has passed in an Exception
            # subclass populated with non-ASCII bytestring data without a
            # working unicode method. Try to handle this without raising a
            # further exception by individually forcing the exception args
            # to unicode.
            s = ' '.join([force_unicode(arg, encoding, errors) for arg in s])
    return s</code></pre>
<p>Estoy convencido de que si tienes problemas con los strings en python, sabrás apreciar este código.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/05/una-de-python-force_unicode/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>mansofk: el super mega ultra lightweight js framework</title>
		<link>http://www.codigomanso.com/es/2010/05/mansofk-el-super-mega-ultra-lightweight-js-framework/</link>
		<comments>http://www.codigomanso.com/es/2010/05/mansofk-el-super-mega-ultra-lightweight-js-framework/#comments</comments>
		<pubDate>Tue, 04 May 2010 19:01:40 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[mooTools]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[js framework]]></category>
		<category><![CDATA[lightweight]]></category>
		<category><![CDATA[mansofk]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=869</guid>
		<description><![CDATA[Me hacía falta un framework de javascript que fuese capaz de cambiar el CSS de los elementos, que fuese capaz de hacer peticiones AJAX,  capaz de cargar javascripts o CSS externos, capaz de añadir o cambiar HTML sobre la marcha, capaz de capturar eventos, capaz de realizar animaciones y capaz de evitar colisiones con otros [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Me hacía falta un framework de javascript que fuese capaz de cambiar el CSS de los elementos, que fuese capaz de hacer peticiones AJAX,  capaz de cargar javascripts o CSS externos, capaz de añadir o cambiar HTML sobre la marcha, capaz de capturar eventos, capaz de realizar animaciones y capaz de evitar colisiones con otros frameworks o incluso con sigo mismo, y además, que fuera superligero y funcionara en IE6+, FF, Safari, Chrome y Opera.</p>
<p style="text-align: justify;">Al final, después de cansarme de buscar y buscar, lo he programado yo, y en honor al blog, he decidido llamarlo <strong>manso framework</strong>. <strong>mansofk</strong> para los amigos.</p>
<p style="text-align: justify;">Al final he conseguido meter toda esta funcionalidad en tan sólo 1.5KB.</p>
<p>Las funcionalidades principales son:</p>
<ul>
<li>Fácil renombrar el framework para evitar colisiones</li>
<li>Soporta encadenamiento de llamadas</li>
<li>Soporta la carga de componentes externos de forma dinámica
<ul>
<li>Soporta cargar CSS externos dinámicamente</li>
<li>Soporta cargar javascript externos dinámicamente</li>
</ul>
</li>
<li>Manipulaciones DOM sencillas
<ul>
<li>Seleccionar elementos por ID</li>
<li>Añadir elementos</li>
<li>Reemplazar elementos</li>
</ul>
</li>
<li>Manipular el estilo CSS de los elementos
<ul>
<li>Obtener una propiedad del estilo actual de un elemento</li>
<li>Cambiar una propiedad del estilo de un elemento</li>
<li>Cambiar varias propiedades a la vez</li>
</ul>
</li>
<li>Animaciones CSS sencillas
<ul>
<li>Soporta varios atributos a la vez</li>
<li>Varios parametros, entre ellos la duración e incluso los frames por segundo</li>
<li>Es posible seleccionar la función linear y la cúbica</li>
</ul>
</li>
<li>Soporte de eventos
<ul>
<li>bind</li>
<li>unbind</li>
</ul>
</li>
<li>Llamadas AJAX
<ul>
<li>Con POST</li>
<li>Con GET</li>
<li>Con soporte XML</li>
<li>Con soporte JSON</li>
<li>Con soporte texto plano</li>
</ul>
</li>
<li>Superligero
<ul>
<li>3.3 KB minified</li>
<li>1.5 KB gzipped!</li>
</ul>
</li>
</ul>
<p style="text-align: justify;">Sois libres de usar este framework para lo que os venga en gana, pero no me responsabilizo de nada.</p>
<p style="text-align: justify;">A continuación teneis la versión sin comprimir, y la versión reducida con <a href="http://closure-compiler.appspot.com/home" target="_blank">Google Closure Compiler</a>:</p>
<ul style="text-align: justify;">
<li style="text-align: justify;"><a href="http://www.codigomanso.com/archives/mansofk/mansofk-1.0.min.js" target="_self">mansofk-1.0.min.js</a> (3.3 KB para usar en producción, si usas gzip ocupa sólo 1.5KB)</li>
<li style="text-align: justify;"><a href="http://www.codigomanso.com/archives/mansofk/mansofk-1.0.js" target="_self">mansofk-1.0.js</a> (11KB para usar durante el desarrollo)</li>
</ul>
<p style="text-align: justify;">Ale, pues ya está. Lo suyo sería hacer  una demo, pero como ahora mismo tengo otras cosas que hacer, me lo dejo  para otra ocasión.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/05/mansofk-el-super-mega-ultra-lightweight-js-framework/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Google App Engine en Ubuntu 10.4 Lucid Lynx</title>
		<link>http://www.codigomanso.com/es/2010/05/google-app-engine-en-ubuntu-10-4-lucid-lynx/</link>
		<comments>http://www.codigomanso.com/es/2010/05/google-app-engine-en-ubuntu-10-4-lucid-lynx/#comments</comments>
		<pubDate>Mon, 03 May 2010 17:06:55 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=863</guid>
		<description><![CDATA[No es nuevo, siempre que actualizo a la siguiente versión de Ubuntu (en este caso la 10.4), me toca pasarme un par de días reconfigurando cosas o reinstalando paquetes.
En fin, que estoy ahora mismo desarrollando una aplicación con Google App Engine (GAE para los amigos), y para no tener problemas al hacer un deployment, lo [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">No es nuevo, siempre que actualizo a la siguiente versión de Ubuntu (en este caso la 10.4), me toca pasarme un par de días <a href="http://www.codigomanso.com/es/2010/04/ubuntu-10-4-poner-el-boton-de-cerrar-la-ventana-a-la-derecha/" target="_self">reconfigurando cosas</a> o reinstalando paquetes.</p>
<p style="text-align: justify;">En fin, que estoy ahora mismo desarrollando una aplicación con <a href="http://code.google.com/appengine/">Google App Engine</a> (GAE para los amigos), y para no tener problemas al hacer un deployment, lo suyo es tener instalado Python 2.5.</p>
<p style="text-align: justify;">Como no, la gente de Canonical ha eliminado el paquete python2.5 de Ubuntu Lucid, así que ya la tenemos montada. No puedo lanzar el servidor local de Google App Engine.</p>
<p style="text-align: justify;">Por suerte, después de estar indagando e indagando en launchpad.net he encontrado a alguien que se lo ha currado y ha creado los <a href="https://launchpad.net/~fkrull/+archive/deadsnakes">paquetes python2.4 y python2.5</a> para Ubuntu Lucid Lynx.</p>
<p style="text-align: justify;">Lo único que tienes que hacer es añadir las siguientes lineas en /etc/apt/sources.list</p>
<pre id="sources-list-entries">deb <a href="http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu">http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu</a> lucid main
deb-src <a href="http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu">http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu</a> lucid main</pre>
<p>Y finalmente ejecutar:</p>
<pre>
$ sudo apt-get update
$ sudo apt-get install python2.5
</pre>
<p style="text-align: justify;">Y ya está, ya puedes ejecutar GoogleAppEngine en Ubuntu Lucid Lynx.</p>
<p>Enlaces de interés:</p>
<ul>
<li><a href="https://launchpad.net/~fkrull/+archive/deadsnakes">Old Python versions en Launchpad</a> (esta es la web donde dice como añadir los paquetes)</li>
<li><a href="http://www.python.org/download/releases/2.5.5/">Python 2.5.5 release page</a></li>
<li><a href="http://code.google.com/appengine/">Google App Engine</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/05/google-app-engine-en-ubuntu-10-4-lucid-lynx/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Ubuntu 10.4: Poner el botón de cerrar la ventana a la derecha</title>
		<link>http://www.codigomanso.com/es/2010/04/ubuntu-10-4-poner-el-boton-de-cerrar-la-ventana-a-la-derecha/</link>
		<comments>http://www.codigomanso.com/es/2010/04/ubuntu-10-4-poner-el-boton-de-cerrar-la-ventana-a-la-derecha/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 11:16:07 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=860</guid>
		<description><![CDATA[Ubuntu 10.4 acaba de salir. Básicamente yo vengo usando Ubuntu desde hace cosa de 4-5 años, y de momento estoy bastante contento.
El gran problema de este release de Ubuntu, a mi parecer, es que han cambiado los botones de control de ventana, y los han puesto a la izquierda, en vez de seguir manteniendolos a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ubuntu.com/">Ubuntu 10.4</a> acaba de salir. Básicamente yo vengo usando Ubuntu desde hace cosa de 4-5 años, y de momento estoy bastante contento.</p>
<p>El gran problema de este release de Ubuntu, a mi parecer, es que han cambiado los botones de control de ventana, y los han puesto a la izquierda, en vez de seguir manteniendolos a la derecha, que es lo que el 95% de los usuarios están acostumbrados.</p>
<p>En fin, que como no me gustaba, he indagado un poco, y la solución ha sido fácil e instantanea:</p>
<p>Hay que pulsar Alt+F2, ponemos el comando gconf-editor y le damos a Enter.</p>
<p>Una vez en el editor de configuraciones, en el desplegable de la izquierda buscamos la ruta <strong>app -&gt; metacity -&gt; general</strong> y  hacemos doble click en el campo que pone <strong>button_layout</strong>.</p>
<p>Símplemente hay que cambiar el campo de valor y poner lo siguiente:</p>
<p><strong>menu:minimize,maximize,close</strong></p>
<p>Se le da a cerrar/guardar, y ale, automaticamente las ventanas se reconfiguran.</p>
<p>Ya volvemos a tener los iconos a la derecha.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/04/ubuntu-10-4-poner-el-boton-de-cerrar-la-ventana-a-la-derecha/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Recupero más de 17 mil fotos en una tarjeta SD corrupta</title>
		<link>http://www.codigomanso.com/es/2010/04/recupero-mas-de-17-mil-fotos-en-una-tarjeta-sd-corrupta/</link>
		<comments>http://www.codigomanso.com/es/2010/04/recupero-mas-de-17-mil-fotos-en-una-tarjeta-sd-corrupta/#comments</comments>
		<pubDate>Sat, 24 Apr 2010 09:33:28 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Administracion de Servidores]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Utilidades]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[ddrescue]]></category>
		<category><![CDATA[foremost]]></category>
		<category><![CDATA[recuperar datos]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=853</guid>
		<description><![CDATA[Pues sí. No voy a explicar los detalles, pero el caso es que por una razón u otra, estaba moviendo las fotos de una tarjeta SD al ordenador, cuando PAAAAM, reseteo del ordenador, con la consiguiente pérdida de las fotos.
Las fotos no estaban ni en el disco duro, ni en la propia tarjeta.  Putada  [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Pues sí. No voy a explicar los detalles, pero el caso es que por una razón u otra, estaba moviendo las fotos de una tarjeta SD al ordenador, cuando PAAAAM, reseteo del ordenador, con la consiguiente pérdida de las fotos.</p>
<p style="text-align: justify;">Las fotos no estaban ni en el disco duro, ni en la propia tarjeta.  Putada <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p style="text-align: justify;">Cual fue mi asombro, cuando me propuse recuperar mis fotos, y en vez de las 69 fotos que yo quería recuperar, ¡¡recuperé 17 mil!!</p>
<p style="text-align: justify;">Vale, para mi estaba claro que iba a recuperar del orden de 500 a 1000 fotos, pero 17 mil! La virgen santa! Mi vida entera en la tarjeta de memoria.</p>
<p style="text-align: justify;">Para el que se encuentre en mi situación, a continuación os doy una pequeña ayuda.</p>
<p style="text-align: justify;">
<p><span style="text-decoration: underline;"><strong>Pasos para recuperar los datos de una tarjeta de memoria, tarjeta USB o disco duro.</strong></span></p>
<p style="text-align: justify;">El tema es que hay gente en el mundo que se lo ha currado bastante, y ha hecho herramientas superútiles y supersencillas para recuperar las fotos.</p>
<p style="text-align: justify;">Me consta que existen programas para Windows, pero como yo uso Linux, pues voy a explicar lo que yo hice.</p>
<p style="text-align: justify;">El primer paso, aunque es de sentido común, es no hacer ninguna operación con la tarjeta o el USB en cuestión. Nada de guardar nuevos archivos, porque podrías estar sobreescribiendo los que quieres recuperar. De hecho, lo mejor que puedes hacer, si tienes espacio suficiente en otro disco, es un volcado de memoria. Es decir, guardar TODA la memoria de la tarjeta, tal cual, en un archivo de tu disco duro. Hay programas especializados.</p>
<p style="text-align: justify;">En mi caso, me descargué los paquetes  <strong>gddrescue</strong> y <strong>foremost</strong> de Debian/Ubuntu.</p>
<p style="text-align: justify;">Lo primero, para generar la imagen, es ejecutar <strong>ddrescue </strong>sobre el dispositivo afectado, guardando el archivo en OTRO dispositivo (de no ser así, lo estaríamos sobreescribiendo y perderíamos los datos).</p>
<p><code>sudo ddrescue -r 3 /dev/&lt;device&gt;  /home/&lt;user&gt;/image.dd /home/&lt;user&gt;/image.dd.log</code></p>
<p style="text-align: justify;">El segundo paso, una vez tenemos la imagen del disco, es usar algún programa para recuperar los archivos. En este punto hay muchas alternativas (ver enlaces de abajo para más detalles). Dado que yo quería recuperar únicamente archivos JPEG de la tarjeta, decidí usar el programa <strong>foremost</strong>.</p>
<p><code>foremost -v -q -t jpeg -i /home/&lt;user&gt;/image.dd -o /home/&lt;user&gt;/foremost/</code></p>
<p style="text-align: justify;">El comando anterior busca archivos en JPG en el archivo <strong>image.dd</strong> y las imágenes encontradas se almacenan en la carpeta /home/&lt;user&gt;/foremost/</p>
<p style="text-align: justify;">Tras 15-20 minutos, recuperé nada menos que 17579 archivos en JPG.  Por suerte para mi, los primeros 69 eran las fotos que yo quería <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p style="text-align: justify;"><strong>Links interesantes:</strong></p>
<ul style="text-align: justify;">
<li><a href="https://help.ubuntu.com/community/DataRecovery">Data Recovery using Ubuntu</a></li>
</ul>
<p style="text-align: justify;"><span style="text-decoration: underline;"><strong>Nota para los despistados y los precavidos:</strong></span></p>
<p style="text-align: justify;">Estos pasos no sólo sirven cuando te ha petado la tarjeta de memoria o el USB, también demuestran lo fácil que puede ser recuperar información de una tarjeta de memoria/USB/disco duro donde alguien se cree que borrando un archivo ya no vas a encontrar nada. Los datos siguen ahí hasta que los sobreescribas (o los borres con algún programa especializado).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/04/recupero-mas-de-17-mil-fotos-en-una-tarjeta-sd-corrupta/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>http_build_query para Python</title>
		<link>http://www.codigomanso.com/es/2010/04/http_build_query-para-python/</link>
		<comments>http://www.codigomanso.com/es/2010/04/http_build_query-para-python/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 21:00:04 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[http_build_query]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=854</guid>
		<description><![CDATA[Para quien le sirva, me he pasado un rato haciendo una función en python que fuera equivalente a http_build_query de PHP.
##
# Mimics the behaviour of http_build_query PHP function
# This method can be useful for sending data to flash applications
##################################################
def http_build_query(params, topkey = ''):
  from urllib import quote

  if len(params) == 0:
   [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Para quien le sirva, me he pasado un rato haciendo una función en python que fuera equivalente a http_build_query de PHP.</p>
<pre><code>##
# Mimics the behaviour of http_build_query PHP function
# This method can be useful for sending data to flash applications
##################################################
def http_build_query(params, topkey = ''):
  from urllib import quote

  if len(params) == 0:
    return ""

  result = ""

  # is a dictionary?
  if type (params) is dict:
    for key in params.keys():
      newkey = quote (key)
      if topkey != '':
        newkey = topkey + quote('[' + key + ']')

      if type(params[key]) is dict:
        result += http_build_query (params[key], newkey)

      elif type(params[key]) is list:
        i = 0
        for val in params[key]:
          result += newkey + quote('[' + str(i) + ']') + "=" + quote(str(val)) + "&amp;"
          i = i + 1

      # boolean should have special treatment as well
      elif type(params[key]) is bool:
        result += newkey + "=" + quote (str(int(params[key]))) + "&amp;"

      # assume string (integers and floats work well)
      else:
        result += newkey + "=" + quote (str(params[key])) + "&amp;"

  # remove the last '&amp;'
  if (result) and (topkey == '') and (result[-1] == '&amp;'):
    result = result[:-1]

  return result</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/04/http_build_query-para-python/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
