Skip to main content

Ralsina.Me — Roberto Alsina's website

People believe anything on the Internet.

I just saw this on a place I won't both­er link­ing:

This oc­to­ber has 5 fri­days, 5 sat­ur­days and 5 sun­days. This hap­pens on­ly ev­ery 823 years. And I am ground­ed all mon­th!

Re­al­ly, it's not worth link­ing to be­cause it's ev­ery­where

There are vari­a­tion­s, of course, 5 sun­day/­mon­day/tues­days, dif­fer­ent month­s, etc.

But why are peo­ple fall­ing for that? I mean, it's pret­ty ob­vi­ous if you think 2 min­utes that there's no way it can be true!

  1. The length of oc­­to­ber is fixed (31 days).

  2. Since weeks are 7 days, you have 4 weeks + 3 days in oc­­to­ber.

  3. If oc­­to­ber starts on a fri­­day, those last three days are go­ing to be fri­­day/sat­ur­­day/­­sun­­day.

So, for this thing to be true, Oc­to­ber 1st would have to be a fri­day on­ly once ev­ery 823 years. Sounds pret­ty stupid when you say it that way, right?

I re­al­ly have no idea how any­one with half a brain can fall for it, but I have seen peo­ple I know have a func­tion­al cor­tex do it. Com­ments en­cour­aged :-)

Como ser un nerd en argentina y no morir en el intento

This is a span­ish-on­ly post, it makes no sense for any en­glish-read­er­s: it's about how to buy elec­tron­ics in Ar­genti­na.


Intro

Ser un nerd en Ar­genti­na tiene mu­chos prob­le­mas. Uno de el­los es que los pre­cios que nos quieren co­brar por casi cualquier chiche elec­tróni­co es ridícu­lo.

Otro de los prob­le­mas es que el 99% de la gente no sabe co­mo hac­er para que no les afa­nen de esa man­er­a. Y ojo, no hablo de con­tra­ban­dear, hablo de us­ar tus dere­chos y tus re­cur­sos legales. Aclaro: no soy abo­gado, si sigu­ien­do es­tos con­se­jos vas pre­so, es cosa tuya, yo di­go lo que creo que es­tá bi­en nomás.

Así que es­ti­ma­dos lec­tores, acá es­tá mi guía para com­prar chich­es sin ten­er que em­peñar un riñón (que tam­bién es ile­gal, ya que es­ta­mos).

Lo primero que nece­sitás es pa­cien­ci­a. Al­gunos de los mecan­is­mos que te voy a con­tar ll­e­van uno o dos meses, o re­quieren co­lab­o­ración de ter­ceros. Pero bueno, so­mos nerd­s, re­solver prob­le­mas es lo nue­stro.

Chucherías Chinas

Ten­go un boni­to mi­cro­sco­pio de bol­sil­lo de 80x que me com­pró mi es­posa. Cos­to? $90. Es un juguete buenísi­mo, re ed­uca­tivo, y cuan­do tenía 6 años hu­biera da­do la fig­u­ri­ta difí­cil (era la tarán­tu­la) por uno de es­tos.

Cos­to en chi­na? U$S 9.39, con en­vío gratis

O sea, la mi­tad. Y co­mo sale menos de U$S 25, de he­cho es le­gal traer­lo por correo y no pagás tasa de ad­u­a­na.

De to­das for­mas, prob­a­ble­mente no ten­gas que ir a la ad­u­a­na porque....

Tip

Cosas chi­cas == no prob­lem

Nor­mal­mente los pa­que­tes de menos de medio ki­lo casi nun­ca se quedan en la ad­u­a­na. Ese don­gle blue­tooth de U$S 1 te va a lle­gar a tu casa.

Pero ponéle que pagás la tasa. Con tasa y todo, son U$S 15, o sea $60. Si pasás por la ad­u­a­na a ve­ces y no te mo­les­ta hac­er co­la un ra­to (ll­e­vate un li­bro)....

Pero es aún mejor. Porque en http://DealEx­treme.­com tenés un mod­e­lo de 150x por U$S 12! De he­cho, tenés 36 mod­e­los de mi­cro­sco­pios!

Tip

El mun­do es grande

Com­prar las cosas di­rec­ta­mente sig­nifi­ca ele­gir de una var­iedad muchísi­mo may­or de la que tenés acá. Sumále que enci­ma es más bara­to...

Por ejem­plo, en http://al­iba­ba.­com hay al­go así co­mo 35000 vende­dores de tablets con An­droid. Al­gu­na te va a servir ;-)

Aho­ra bi­en, supong­amos que te de­cidiste y te en­car­gaste al­go de Chi­na o sim­i­lar, qué tenés que saber:

  • Guardá la "fac­­tu­ra" que te dá el sitio, y la URL del pro­­duc­­to.

    La fac­­tu­ra suele ser un HT­M­L, im­primí­­lo. Cuan­­do re­tirás en Ad­u­a­­na lo nece­sitás. No lo muestres de en­­trada! Só­­lo si te lo pi­­den.

  • Andá dis­­puesto a pa­­gar. Es al cuete dis­­cu­tir. Tené en cuen­­ta que aún con lo de la ad­u­a­­na es bara­­to, y no te ha­­gas mala san­­gre.

  • Si vas tipo 10:30 suele haber poca gente.

  • Andá tran­quilo, ll­e­­vate al­­go para en­treten­erte porque en una de esas ll­e­­va un ra­­to. Igual hay sil­las, que se yó, no es la muerte de nadie.

Tip

It's a gift!

Casi to­dos es­tos sitios tienen al­gún ser­vi­cio de "gift". Te sacan el pre­cio y to­do lo que ha­ga que parez­ca una com­pra por in­ter­net. Au­men­ta la prob­a­bil­i­dad de que llegue a tu casa di­rec­to.

Cómo Pagar

La más fá­cil es Pay­Pal. Si tenés tar­je­ta de crédi­to es triv­ial.

Tip

Hablá con nerds amigos!

Si no tenés Pay­Pal ni tar­je­ta in­ter­na­cional, pero conocés al­guien que tra­ba­ja para el ex­te­ri­or, es muy prob­a­ble que esa per­sona ten­ga sal­do en Pay­Pal que no puede sacar. En Ar­genti­na, con­ver­tir Pay­Pal en dinero es muy caro. En­tonces se puede lle­gar a un acuer­do: se lo pagás al 95% del val­or (o lo que ar­reglen) tu ami­go tiene la plata, vos tenés de­s­cuen­to en dealex­treme o donde sea.

Tam­bién podés hac­er la com­pra con la tar­je­ta de un amigo/­pari­ente y pa­gar­le a él en efec­ti­vo.

El amigo que viene de afuera

Sí tenés un cono­ci­do que vi­a­ja al ex­te­ri­or con reg­u­lar­i­dad:

  • Podés com­prar en USA y que te re­ci­­ba y traiga las cosas.

  • Has­­ta U$S 300 (si el que vi­a­­ja es ar­­gen­ti­no) no se pa­­ga ad­u­a­­na. Se pa­­ga el 50% por en­ci­­ma de esa cifra.

  • Si es un ex­­tran­­jero que trae una cosa propia "en uso" y te la vende acá, no creo que ten­­gas que pa­­gar im­­portación (no es­­­toy se­guro)

Veamos un ejem­plo!

  • Una HP mi­ni com­pra­­da acá: $1999, o U$S 500

  • Com­pra­­da en US­A: U$S 329.

    • Pa­­­gan­­­do ad­u­a­­­na con fran­qui­­­ci­a: U$S 345

    • Pa­­­gan­­­do ad­u­a­­­na ful­l: U$S 495 (ahí no con­viene ;-)

Tip

Los pro­duc­tos HP tienen garan­tía in­ter­na­cional

Los Dell por ejem­plo: NO. Así que ojo, com­prá una mar­ca que te dé ser­vice en Ar­genti­na. En el ca­so de Dell tenés que com­prar aparte una garan­tía que te sir­va acá. Vos sabrás si te bancás ten­er una note­book sin garan­tía (yo sí, si es bara­ta ;-)

Pero que te pare­cería ten­er la mis­ma net­book por U$S 180?

Bueno, re­sul­ta que HP (y to­das las em­pre­sas) venden pro­duc­tos "re­fur­bished" o sea rea­condi­ciona­dos. Nor­mal­mente no te vas a dar cuen­ta de nada, tienen un rayón mín­i­mo, o al­go así. Hoy la mis­ma net­book es­ta­ba a U$S 179.90. Nor­mal­mente salen más o menos la mi­tad. Y vienen con garan­tía.

Y fi­játe que la HP mi­ni por U$S 180, pa­gan­do la ad­u­a­na ful­l... cues­ta el 54% de lo que sale la nue­va acá. Eso es ne­go­cio.

Tip

La en­tre­ga es al­lá

Nor­mal­mente las com­pras de re­fur­bished hay que hac­er­las en US­A. Por eso lo de que tiene que ir al­guien a recibir­la.

Al­ter­na­ti­va­mente hay ser­vi­cios de reen­vío de mer­cadería, pero no los he us­a­do y no los conoz­co.

Al­ter­na­ti­va­mente, Ciu­dad del Este (Paraguay) es­tá muy cer­ca de Ar­genti­na. Y es muy bara­to com­prar elec­tróni­cos ahí. Y tenés los U$S 300 de fran­qui­ci­a.

Pero hay más! Un ciu­dadano paraguayo que visi­ta ar­genti­na puede traer cier­tas cosas con cier­tos límites. Hay que hablar con él y co­or­di­nar!

Si no conocés a nadie... bueno, andá de paseo a cataratas! Pasala bi­en! Y com­prate una cá­mara o lo que sea en la ex­cur­sión a Ciu­dad del Este.

Accesorios

No com­pres ac­ce­so­rios orig­i­nales. Por ejem­plo: la batería orig­i­nal de re­puesto de mi eeePC 701? U$S 110, 3 el­e­men­tos. La "trucha" de 6 el­e­men­tos? U$S 40.

Tip

Es ile­gal im­por­tar cosas que se ench­u­fan

To­do lo que se enchufe a la pared tiene que ho­molog­a­rse y creo que es ile­gal traer­lo. Si al­guien tiene un car­gador para su propia note­book por ejem­plo, supon­go que es le­gal (así me hice de un car­gador para la eee)

Conclusión

Ojalá sir­va de al­go, si tenés más tips pone­los en los co­men­tar­ios!

Making your app modular: Yapsy

That a plug­in ar­chi­tec­ture for a com­plex app is a good idea is one of those things that most peo­ple kin­da agree on. One thing we don't quite agree is how the heck are we go­ing to make out app mod­u­lar?

One way to do it (if you are cod­ing python) is us­ing Yap­sy.

Yap­sy is awe­some. Al­so, yap­sy is a bit un­der­doc­u­ment­ed. Let's see if this post fix­es that a bit and leaves just the awe­some.

Up­date: I had not seen the new Yap­sy doc­s, re­leased a few days ago. They are much bet­ter than what was there be­fore :-)

Here's the gen­er­al idea be­hind yap­sy:

  • You cre­ate a Plug­in Man­ag­er that can find and load plug­ins from a list of places (for ex­am­­ple, from ["/us­r/share/ap­p­­name/­­plu­g­in­s", "~/.ap­p­­name/­­plu­g­in­s"]).

  • A plug­in cat­e­­go­ry is a class.

  • There is a map­ping be­tween cat­e­­go­ry names and cat­e­­go­ry class­es.

  • A plug­in is a mod­­ule and a meta­­da­­ta file. The mod­­ule de­fines a class that in­­her­its from a cat­e­­go­ry class, and be­­longs to that cat­e­­go­ry.

    The meta­­da­­ta file has stuff like the plug­in's name, de­scrip­­tion, URL, ver­­sion, etc.

One of the great things about Yap­sy is that it does­n't spec­i­fy too much. A plug­in will be just a python ob­jec­t, you can put what­ev­er you want there, or you can nar­row it down by spec­i­fy­ing the cat­e­go­ry class.

In fac­t, the way I have been do­ing the cat­e­go­ry class­es is:

  • Start with an em­p­­ty class

  • Im­­ple­­ment two plug­ins of that cat­e­­go­ry

  • If there is a chunk that's much alike in both, move it in­­­to the cat­e­­go­ry class.

But trust me, this will all be clear­er with an ex­am­ple :-)

I will be do­ing it with a graph­i­cal PyQt ap­p, but Yap­sy works just as well for head­less of CLI app­s.

Let's start with a sim­ple ap­p: an HTML ed­i­tor with a pre­view wid­get.

//ralsina.me/static/yapsy/editor1.jpeg

A sim­ple ed­i­tor with pre­view

Here's the code for the ap­p, which is re­al­ly sim­ple (it does­n't save or do any­thing, re­al­ly, it's just an ex­am­ple):

ed­i­tor1.py

from PyQt4 import QtCore, QtGui, QtWebKit
import os, sys

class Main(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.layout = QtGui.QVBoxLayout()
        self.editor = QtGui.QPlainTextEdit()
        self.preview = QtWebKit.QWebView()
        self.layout.addWidget(self.editor)
        self.layout.addWidget(self.preview)
        self.editor.textChanged.connect(self.updatePreview)
        self.setLayout(self.layout)

    def updatePreview(self):
        self.preview.setHtml(self.editor.toPlainText())

def main():
    # Again, this is boilerplate, it's going to be the same on
    # almost every app you write
    app = QtGui.QApplication(sys.argv)
    window=Main()
    window.show()
    # It's exec_ because exec is a reserved word in Python
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Note

From now on list­ings will not in­clude the main func­tion, be­cause it nev­er changes.

But this ap­pli­ca­tion has an ob­vi­ous lim­it: you have to type HTML in it. Why not type python code in it and have it con­vert to HTML for dis­play? Or Wi­ki markup, or re­struc­tured tex­t?

You could, in prin­ci­ple, just im­ple­ment all those mod­es, but then you are as­sum­ing the re­spon­s­abil­i­ty of sup­port­ing ev­ery thing-that-­can-be-­turned-in­to-HTM­L. Your app would be a mono­lith. That's where yap­sy en­ters the scene.

So, let's cre­ate a plug­in cat­e­go­ry, called "For­mat­ter" which takes plain text and re­turns HTM­L. Then we add stuff in the UI so the us­er can choose what for­mat­ter he wants, and im­ple­ment two of those.

Here's our plug­in cat­e­go­ry class:

cat­e­gories.py

class Formatter(object):
    """Plugins of this class convert plain text to HTML"""

    name = "No Format"

    def formatText(self, text):
        """Takes plain text, returns HTML"""
        return text

Of course what good is a plug­in ar­chi­tec­ture with­out any plug­ins for it? So, let's cre­ate two plug­ins.

First: a plug­in that takes python code and re­turns HTM­L, thanks to pyg­ments.

plu­g­in­s/pyg­men­tize.py

from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter

from categories import Formatter

class Pygmentizer(Formatter):
    name = "Python Code"

    def formatText(self, text):
        return highlight(text, PythonLexer(), HtmlFormatter(full=True))

See how it goes in­to a plug­ins fold­er? Lat­er on we will tell yap­sy to search there for plug­ins.

To be rec­og­nized as a plug­in, it needs a meta­da­ta file, too:

plu­g­in­s/pyg­men­tize.yap­sy-­plu­g­in

[Core]
Name = Python Code
Module = pygmentize

[Documentation]
Author = Roberto Alsina
Version = 0.1
Website = //ralsina.me
Description = Highlights Python Code

And re­al­ly, that's all there is to mak­ing a plug­in. Here's an­oth­er one for com­par­ison, which us­es do­cu­tils to for­mat re­Struc­tured Tex­t:

plu­g­in­s/rest.py

from categories import Formatter
import docutils.core
import docutils.io


class Rest(Formatter):
    name = "Restructured Text"

    def formatText(self, text):
        output = docutils.core.publish_string(
            text, writer_name = 'html'
        )
        return output

plu­g­in­s/rest.yap­sy-­plu­g­in

[Core]
Name = Restructured Text
Module = rest

[Documentation]
Author = Roberto Alsina
Version = 0.1
Website = //ralsina.me
Description = Formats restructured text

And here they are in ac­tion:

//ralsina.me/static/yapsy/editor2.jpeg

reSt mode

//ralsina.me/static/yapsy/editor3.jpeg

Python mode

Of course us­ing cat­e­gories you can do things like a "Tool­s" cat­e­go­ry, where the plug­ins get added to a Tools menu, too.

And here's the ap­pli­ca­tion code:

ed­i­tor2.py

from categories import Formatter
from yapsy.PluginManager import PluginManager

class Main(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.layout = QtGui.QVBoxLayout()
        self.formattersCombo = QtGui.QComboBox()
        self.editor = QtGui.QPlainTextEdit()
        self.preview = QtWebKit.QWebView()

        self.layout.addWidget(self.formattersCombo)
        self.layout.addWidget(self.editor)
        self.layout.addWidget(self.preview)

        self.editor.textChanged.connect(self.updatePreview)
        self.setLayout(self.layout)

        # Create plugin manager
        self.manager = PluginManager(categories_filter={ "Formatters": Formatter})
        self.manager.setPluginPlaces(["plugins"])

        # Load plugins
        self.manager.locatePlugins()
        self.manager.loadPlugins()

        # A do-nothing formatter by default
        self.formattersCombo.addItem("None")
        self.formatters = {}
        print self.manager.getPluginsOfCategory("Formatters")
        for plugin in self.manager.getPluginsOfCategory("Formatters"):
            print  "XXX"
            # plugin.plugin_object is an instance of the plugin
            self.formattersCombo.addItem(plugin.plugin_object.name)
            self.formatters[plugin.plugin_object.name] = plugin.plugin_object

    def updatePreview(self):
        # Check what the current formatter is
        name =  unicode(self.formattersCombo.currentText())
        text = unicode(self.editor.toPlainText())
        if name in self.formatters:
            text = self.formatters[name].formatText(text)
        self.preview.setHtml(text)

In short: this is easy to do, and it leads to fix­ing your ap­pli­ca­tion's in­ter­nal struc­ture, so it helps you write bet­ter code.

Full source code for ev­ery­thing.


Contents © 2000-2021 Roberto Alsina