jueves, 10 de julio de 2008

Kernel de crema americana

A veces me pongo a pensar en lo pelotudos que son algunos rótulos del mundo informático, en particular del software libre.

Cuando escuché por primera vez la palabra Debianita para un usuario de Debian, agradecí ser un Gentoosero (¿?) porque ese calificativo parece que le quita todo el valor al esfuerzo de ser un usuario de Debian. Merecen algo más del tipo Debianero y no algo que suena a nenita, o que parece el diminutivo de algo.

Ahora escuché a un amigo decir que se compila su propio kernel. Que se baja un "kernel vainilla" y le aplica los parches que quiere. El término vanilla ya lo había leído en varios lugares para referirse a un producto sin modificaciones, tal como lo publica el desarrollador. Pero esta fue la primera vez que lo escuchaba castellanizado.

Supongo que una versión más argentina sería un "kernel pelado", o algo así. Pero me puse a buscar de dónde salía el termino vanilla para este tipo de cosas, y por lo que leí viene de que el sabor más popular para los "ice creams" es la vainilla, entones la opción vainilla sería como la estándard.

Acá no pasa eso, el gusto más neutral es el de crema americana, que viene por default en los pinitos, los pinguinitos, y ciertos postres helados... así que para cerrar este pequeño divague, propongo el siguiente logo para identificar al kernel recién salido de fábrica:


Este post claramente está hablando del fasoooo.

lunes, 19 de mayo de 2008

Zambayonny - Las cosas que dejé (Acordes para guitarra)

Había escuchado muy poco de este tipo y si bien me había resultado bastante gracioso no me pareció tan genial. Pero este tema la rompe, y la canción final de tres renglones con la que cierran el programa es algo que se puede definir solo con una palabra: jakkajskjaskjdkaskjakjsdakjkjaskjaskjadskjdak.





La cuestión es que quería los acordes de guitarra para la canción, pero en La cuerda no estaban, así que lo transcribí y lo subí a esa página.
Como tardan cerca de 2 semanas en actualizar, dejo el link a mi página y después actualizo:
Acordes

Si encuentran algún error, avisen. Estuve en duda si el Mi era menor o mayor, porque la secuencia sería como la del recontra usado Canon de Pachelbel si fuese menor, pero parece que es mayor. Y también tengo dudas en
Dm C G C G
podría ser
Dm Am G C G
en el video no se ve bien...



De yapa, me parece que así es la cancioncita del final:

C
No, no me hables de amor
Dm
mientras me chupas la pija
F G C
porque no se te entiende nada

F C


Es el fragmento de la canción "Una semana de mierda"

Update 04/06/2008:
Ya está la transcripcion en La Cuerda

Update 28/07/2008:
Buuh... que turbio... Reemplazaron mi tab por otro donde le cambiaron de cifrado americano a do re mi fa y mi tab desapareció por completo :' (

sábado, 3 de mayo de 2008

4 segundos



No soy un lector de comics. Creo que es una de las pocas cosas del mundo nerdista que me rodea que no se me pegó. El único comic que leí casi completo y que compré casi todos los números fue Cazador.
Ahora (obvio, con 8 años de retraso) descubrí este otro comic argentino, 4 segundos. No es más que la historia de 4 pibes comunes, nada de super héroes ni naves espaciales. Y por eso me gustó. En una noche al pedo leí las 7 historietas y me entretuvo mucho. Lástima que no la hayan seguido.
Está mucho más cerca de los sitcoms que estoy viendo últimamente que de las historietas del gordo de los Simpsons, así que se la recomiendo a todos los que por haber tomado Drink Z con alto contenido de pentaxanol, o algún otro misterio de la vida lleguen a este blog.

Acá les dejo algunos links que les pueden interesar:

http://4segundos.4t.com/
http://www.historieteca.com.ar/4segundos/4segundos.htm
http://www.taringa.net/posts/125795
http://www.taringa.net/posts/arte/818558/4-Segundos---Coleccion-Completa-(Editado).html

Disfrútenlos, tienen más glamour que Chabreleaux.

sábado, 26 de abril de 2008

BadRequest error running the import steps of a selected profile from a product with several profiles

I had to add an action to a content type named "Attachment" for a Plone 3 product. That is just adding the action in the profiles/default/types/Attachment.xml generated by ArchGenXML 2.0. But there is a problem. That file has no special sections for custom code, so it will be overwritten every time we regenerate the product from our model.

My first attempt was to create another profile, called attachment, where I will put the modifications, and running the step from the Install.py. That is:

  • create a profiles/attachment/types/Attachment.xml and include there the action I need to add in a proper xml structure.

  • register the profile in the main configure.zcml (archgenxml will create a profiles.zcml for this purpose)
<!-- ##code-section profiles.zcml-top #fill in your manual code here -->
<genericsetup:registerProfile
name="attachment"
title="MyProduct-customized-profile"
directory="profiles/attachment"
description="Customized extension profile for MyProduct."
provides="Products.GenericSetup.interfaces.EXTENSION"
/>
<!-- ##/code-section profiles.zcml-top -->

  • put this code in Extensions/Install.py
from Products.CMFCore.utils import getToolByName

def afterInstall(self, reinstall, product):
portal_setup = getToolByName(self, 'portal_setup')
portal_setup.runAllImportStepsFromProfile('profile-Products.MyProduct:attachment')


But when I installed the product, I got:

BadRequest: The id "import-all-profile-Products.MyProduct_attachment-20080426230436.log" is invalid - it is already in use.


I was importing the steps of a profile that QuickInstaller had already imported. But my product wasn't completely installed yet...

The problem is that QuickInstaller imported the attachment profile not because it imports every step, but because it imports the first registered profile in alphabetical order. At least, that's what I concluded, because, after moving profiles/attachment to profiles/extra, and renaming attachment for extra in the previous fragments of code, it worked.

The default profile wasn't imported. And looking at the installable products on QuickInstaller Control Panel page, the attachment product was listed, instead of the MyProduct profile that used to be there.

So, should I use only names that follows 'default' in lexicograpic order for additional profiles? I would expect that QuickInstaller only executed the default profile. Maybe I missed something... This was the first time I added a second profile.

jueves, 24 de abril de 2008

How to register a local utility in Plone 3 and not lose its persistent data when the product is reinstalled

What you are about to read is not a great solution. There are probably better ways of doing this, but I wanted to share the problems I found and how I solved, because it took me some time to find out what was going on, and perhaps this can be useful for somebody. So, actually this isn't a HOWTO, it's a HOWIDID.

I was developing a Plone 3 (3.0.6) product, generated with ArchGenXML 2.0, and my objective was to add a local utility to it, which should store a list of items. Those items should be added or removed from a page accessible from the Control Panel, and that list would be the options of a drop down selection field of a content type.

Martin Aspeli's book "Profesional Plone Development" was of great help. How to create the configuration page in the Control Panel was almost copying and paste one of his examples (declaring the configlet in controlpanel.xml, creating a view that extends ControlPanelForm, declaring the icon in actionicons.xml and registering it as a resource, etc)

The problem was that he uses the componentregistry import step to register the utility. And that looks really nice, but if you install your product with quickinstaller, quickinstaller runs this step, and somehow it remembers that the utility belongs to that product, and when you remove the product, you will lose all your persisted data.

I tried some things I found on the web but nothing worked, so I desisted with component registry.

I just used the good old Extensions/Install.py, to which I was familiar from Plone 2.5, and registered the utility there. Neither the file or the directory existed (I guess because with ArchGenXML 2.0 everything that was done there is now done through GenericSetup) so I created them.

The utility must be registered in the afterInstall method. Otherwise QuickInstaller will still remove the data.


Lets say we have this code in utility.py in our product:
class IMyUtility(Interface):

types = schema.List(title=_(u'My list'),
description=_(u'A list of items'),
required=False,
value_type=schema.TextLine(title=u'Item'))

class MyUtility(Persistent):
implements(IMyUtility)



We will write this code en Extensions/Install.py:
def afterInstall(self, reinstall, product):
from Products.MyProduct.utility import IMyUtility, MyUtility
from Products.CMFCore.utils import getToolByName

portal = getToolByName(self,'portal_url').getPortalObject()
sm = portal.getSiteManager()
if not sm.queryUtility(IMyUtility):
sm.registerUtility(MyUtility(),
IMyUtility)


That's it. That works fine if we install our product as an independent product. But there is a problem if we install it as a dependency of a policy product. In that case, Quickinstaller will remember that the utility was created during the installation of the policy product, so the persisted data will survive the reinstallation of the product, but not the reinstallation of the policy product.

In that case, I don't know how to proceed. What I did was to leave the registration code commented in the product Install.py and copy it to the Install.py of the policy product. That sucks, because that registration shouldn't be done by the policy product, but I couldn't imagine another solution.

Do you know one? Leave a comment! :)

UPDATE 16/05/08:
Warning! I don't know exactly why, but after working for a while on my product, I did an update to the whole buildout and I got a:

Error Type: AttributeError
Error Value: type object 'IMyUtility' has no attribute '__iro__'

that broke my Plone Site completely, I can't access anything even from the ZMI. There is not much information about this error on Google, and it is not clear if it is because of this method for registering the utility. Probably yes, so use it at your own risk, and always make backups before updating.

miércoles, 12 de marzo de 2008

Presentando DeFlog

Las tecnologías de la denominada Web 2.0 trajeron al usuario la posibilidad de formar parte de la web, mediante sitios colaborativos, como wikis, o redes sociales como blogs y fotologs.
En algunos casos, los grupos de usuarios de estos sitios, pasan de ser comunidades virtuales, a tribus urbanas.
Los floggers, como se denomina a los usuarios de fotologs, llevan a cabo reuniones frecuentes, y como toda tribu urbana, tienen sus códigos. Algunos se concentran en criticar su vestimenta o cortes de pelo. A mi mucho no me calienta, uno también fue adolescente... pero el lenguaje que usan para comunicarse en la web es algo que me cuesta tolerar. Éste puede resultar críptico para quienes hemos pasado hace algún tiempo nuestra adolescencia y de dolorosa lectura para los que sentimos el equivalente a una patada en los huevos cuando vemos una falta de ortografía en un texto.

En un intento por salvar a la juventud del flagelo del lenguaje fotolog y SMS, creé DeFlog (o Deflog, porque ya hice así el logo) . Un traductor Fotolog -> Español.

Bueno, basta de boludez. Nada más estaba al pedo y quería experimentar con algún framework para desarrollo web diferente al Zope/Plone que vengo usando en el trabajo. Un amigo me mostró algo de Django. También estuve leyendo un poco de Pylons, y en el camino me crucé con CherryPy, que era más que suficiente para lo que quería hacer. Llegué a tener algo bastante completo, pero cuando empecé a tener problemas para tratar palabras con caracteres acentuados y demás (no era la primera vez que me traían dolores de cabeza), decidí dejar Python y hacer lo que hace la mayoría. Usar PHP.
La traducción fue bastante directa y rápida, ya que el código era simple (expresiones regulares, que tienen casi la misma notación, o simples reemplazos de subcadenas por cadenas de algún arreglo)

El traductor puede corregir con bastante éxito los siguientes features del lenguaje flogger
  • Contaminación con abreviaturas típicas del SMS. (xq, tkm, bss, dsp,...)
  • Alternación de mayúsculas y minúsuclas (AlGuNa LeTrA dE uNa CaNcIoN)
  • Repetición de letras (hoooolllaaaaaa!!!!)
  • Omisión de la letra u en la subpalabra 'qu' , o bien, reemplazo de la subpalabra por 'k' (qiero, kiero)
  • Pero a veces la k reemplaza a 'ca' y otras veces, simplemente reemplaza a la letra c (kompré kafé komo loko y me agarró kgadera, ke kgada k me mandé) (este es uno de los puntos con más probabilidad de falla)
  • Faltas ortográficas intencionales como soi, voi, i en lugar de y, etc.
  • Porteñización (vistes, fuistes) (este viene de yapa porque no es particular del vocabulario flogger)

El traductor no contempla los siguientes:
  • Vocabulario aniñado (?) (te kelo muto, pobde Lodemzo, etc)
  • Zezeozizmo (tiene la opción desactivada porque no es mucho más inteligente que reemplazar todas las 'z' por 's')
  • Faltas ortográficas, salvo algunas muy comunes como llendo (¡Es yendo! ¡Hay gente que lo agrega al diccionario del celular porque piensa que no trae la palabra!)
Está desarrollado para dialecto flogger argentino. Su efectividad decaerá en fotologs de otros países.

Pueden probarlo aquí: http://www.santiagobruno.com.ar/php/desfotologuear.php

Este es un ejemplo especialmente seleccionado para ver sus características

Es muy básico, en muchos casos va a andar mal, pero esto fue un juego, lo posteo nada más porque a alguien le puede resultar chistoso o simpático. Me gustaría hacer que se traduzca una página, pero ni daaaaa!!! aahrrreeee!!

Ah, y en conclusión, no aprendí nada de ninguno de los frameworks mencionados, porque fue un programa muy pelotudo, pero ¿qué querés? Me divierte hacer estas huevadas...

Chau, blds!!!!

Update 07/04/2008:
¿No será mucho?

Update 31/05/2008:
Claro que no es mucho. Aún hay más. Solucioné los problemas que tenía inicialmente con Python, y agregué esa versión. (ver en google code)

Update 28/07/2008:
Ahora estuve haciendo un parser re pedorro para traducir una página web. Anda bastante bien para los fotologs, pero el problema es obtener la página externa.
La versión en javascript solo me anduvo en Konqueror, porque por cuestiones de seguridad los requests con javascript están limitados al mismo dominio de la página. Aparentemente a Konqueror no le importa, pero en los otros navegadores no me anda.
Para la versión en php es necesario tener el servidor configurado con algunas excepciones, y no es el caso del proveedor donde tengo la página, así que tengo como resultado
file_get_contents(): URL file-access is disabled in the server configuration
Solo subí la versión en Python ya que esa solo se ejecuta localmente.

sábado, 8 de marzo de 2008

MobiGM "ported" to Python

Reciently, a friend told me about MobiGM, a simple Perl script that parses a rss feed from a gmail account, and sends notifications about new mails to an email account. Ideally, to the one corresponding to your cell phone.

He was having troubles trying to run the script. The problem was simple: The link to the code was dead, and copying and pasting the fragments of code didn't work, because some html special characters were bothering. A few replacements made the script go.

It worked fine sending mails through my ISP SMTP server, since it doesn't require authentication, but I couldn't send mails from my gmail account.
I tried modifying the script, using the module Net::SMTP::SSL, but I had no luck, so I decided to write it in Python.

It works. It has the same functionality as MobiGM and can authenticate against a SMTP server with TLS. But it uses minidom to parse the rss feed, and access to its data in a very direct way, assuming that the feed has always the correct format.
I recommend reading the original post of MobiGM from its author's blog, because it is a nice tutorial on how to build a small application to solve a problem, using various open source tools.
The program itself is not very useful, since you can do the same thing with gmail's filters. But the author remarks the posibility of customizing it, to make it react dinamically to what appears in your mailbox.


Having said that, here is the code:

#!/usr/bin/python

from xml.dom.minidom import parse

SMTP_SERVER = "smtp.yourisp.com:port" #port not needed on servers
#that listen to on port 25
#for gmail use 587,

REQUIRES_AUTHENTICATION = True
REQUIRES_TLS = True
SMTP_USERNAME = 'username'
SMTP_PASSWORD = 'password'
FROM_EMAIL = 'email@isp.com'
TO_EMAIL = 'cellphone@phonecompany.com'

def sendMail(message):
import smtplib
s = smtplib.SMTP(SMTP_SERVER)
#s.debuglevel = 5
s.ehlo()

if REQUIRES_TLS:
s.starttls()
s.ehlo()
if REQUIRES_AUTHENTICATION:
s.esmtp_features["auth"] = "LOGIN PLAIN"
s.login(SMTP_USERNAME, SMTP_PASSWORD)

s.sendmail(FROM_EMAIL, TO_EMAIL, message)
s.quit()


oldIDs = []
newIDs = []

try:
OLDID = open('ids.old', 'rw')
except:
OLDID = None
newfile = open('ids.old', 'w')
newfile.close()

if OLDID:
for line in OLDID.readlines():
oldIDs.append(line.strip())

try:
xmldoc = parse('atomfeed')
except IOError:
quit("Error opening file 'atomfeed'")
except:
quit("Problem parsing file 'atomfeed'")

entries = xmldoc.getElementsByTagName('entry')

for entry in entries:
curID = entry.getElementsByTagName('id')[0].firstChild.nodeValue
newIDs.append(curID)
if not curID in oldIDs:
curTitle = entry.getElementsByTagName('title')[0].firstChild.nodeValue
curContents = entry.getElementsByTagName('summary')[0].firstChild.nodeValue
curAuthorEmail = entry.getElementsByTagName('email')[0].firstChild.nodeValue
curAuthor = entry.getElementsByTagName('name')[0].firstChild.nodeValue
sendMail('Subject:'+ curTitle + '\n\nFrom:' + curAuthorEmail + ' [' + curAuthor + ']\n' + curContents)


OLDID = open('ids.old', 'w')

for newid in newIDs:
OLDID.write(newid + '\n')

OLDID.close()


As Perl's version, this script needs to be added to a shell script, where wget will be executed before it to receive the feed. And that script should be executed periodically by cron.
If we saved this script as mail.py, the shell script would be something like this:

#!/bin/sh
wget -O atomfeed https://mail.google.com/gmail/feed/atom --http-user=gmail.user@gmail.com --http-password=gmailPassword
./mail.py



Read the original post on MobiGM author blog for more details.