Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre python (publicaciones antiguas, página 81)

Nikola: Filters & Bundles

Two up­com­ing fea­tures for the next re­lease of Niko­la, my stat­ic site gen­er­a­tor, due some­time in Au­gust.

Filters

Fil­ters let you post­pro­cess your out­put. Think of it like in­sta­gram for web­sites, but use­ful. You can con­fig­ure per file ex­ten­sion a se­ries of python func­tions or shell com­mand­s, which will be ap­plied in place to the out­put file.

For ex­am­ple, sup­pose you want to ap­ply yui-­com­pres­sor to your CSS and JS files:

FILTERS = {
    ".css": [filters.yui_compressor],
    ".js": [filters.yui_compressor],
}

There, filters.yui_compressor is a simple wrapper around the command so that it applies in-place to the output files.

If you use strings there (untest­ed), they are tak­en as com­mand­s. The "%s" will be re­placed by the file­name, the usu­al crazy shell quot­ing rules ap­ply:

FILTERS = {
    ".jpg": ["jpegoptim '%s'"],
    ".png": ["pngoptim '%s'"],
}

Keep in mind that the fil­ters mod­i­fy the out­put of Niko­la, not the in­put, so your im­ages, CSS, and JS files will not be touched in any way. And of course chang­ing the fil­ters ap­plied to a file will force a re­build, so you can ex­per­i­ment freely.

Bundles

Hav­ing many sep­a­rate CSS or JS files is usu­al­ly a nono for per­for­mance rea­sons be­cause each one may in­volve a sep­a­rate HTTP trans­ac­tion. The so­lu­tion is to "bundle" those files in a sin­gle, larg­er file.

The rea­son not to do that is that usu­al­ly it means hav­ing a huge, un­com­fort­able thing to han­dle. So Niko­la tries to give you the best of both world­s, by let­ting you have sep­a­rate files, and bundling them (or not) on build.

There is a new option, USE_BUNDLES that defaults to False, and there are some changes in the theme templates so that it uses the bundled version when needed.

This was on­ly pos­si­ble thanks to We­bas­sets. How­ev­er, if you don't have We­bas­sets in­stalled, or you don't en­able USE_BUNDLES, this should cause no changes in the out­put.

Conclusion

These new fea­tures will al­low Niko­la users to im­prove their site's per­for­mance with min­i­mal tweak­ing, which is al­ways a good thing.

Clavando un clavo con un zapato I: Do-Sheet.

  1. Te ha­­ce pen­sar di­­fe­­ren­­te.

  2. Es di­­ve­r­­ti­­do.

Lo ma­lo es, por su­pues­to, que el con­te­ni­do de la char­la tie­ne que ser se­cre­to, o no tie­ne nin­gu­na gra­cia. Co­mo el pro­ce­so de re­view pa­ra char­las de Py­Co­nAr es pú­bli­co, no te­nía ma­ne­ra de ex­pli­car de qué se tra­ta­ba.

Co­mo eso sig­ni­fi­ca que pon­go a los re­vi­so­res en el com­pro­mi­so de te­ner que acep­tar mi pa­la­bra de que es­ta char­la es al­go in­te­re­san­te, y eso es injus­to pa­ra ellos y los de­más char­la­ri­nes, can­ce­lé la pro­pues­ta.

La (tal ve­z) bue­na no­ti­cia es que aho­ra to­dos van a po­der ver de qué se tra­ta­ba la char­la. Acá es­tá el cla­vo nú­me­ro 1: Es­cri­bir una ho­ja de cál­cu­lo usan­do doi­t.

Es­ta no es mi pri­me­ra "ho­ja de cál­cu­lo­". To­do em­pe­zó ha­ce mu­cho, mu­cho tiem­po con una fa­mo­sa re­ce­ta de Ra­y­mond He­ttin­ger que he usa­do una y otra y otra vez (ca­paz que fal­ta al­gu­na).

Da­do que ven­go usan­do doit pa­ra Niko­la es­toy im­pre­sio­na­do con lo po­ten­te que es. En bre­ve, doit te per­mi­te crear ta­rea­s, y esas ta­reas de­pen­den de otra­s, ope­ran en da­to­s, dan re­sul­ta­dos que otras ta­reas usan, etc.

¿Se ve adon­de va es­to?

Acá va el có­di­go, con ex­pli­ca­cio­nes:

cells es nuestra hoja. Podés poner cualquier cosa, pero usá siempre el formato "nombre=formula" y la fórmula tiene que ser Python válido ¿ok?

from tokenize import generate_tokens

cells = ["A1=A3+A2", "A2=2", "A3=4"]
values = {}

task_calculate crea una tarea para cada celda, llamada calculate:NOMBRE. La acción que esa tarea realiza es evaluar la fórmula. Pero para hacer eso de manera exitosa, necesitamos saber qué otras celdas hay que evaluar primero.

Eso lo im­ple­men­té usan­do las cal­cu­lated de­pen­den­cies de doi­t, con la ta­rea "ge­t_­de­p:­FOR­MU­LA" pa­ra la fór­mu­la de es­ta cel­da.

def evaluate(name, formula):
    value = eval(formula, values)
    values[name] = value
    print "%s = %s" % (name, value)

def task_calculate():
    for cell in cells:
        name, formula = cell.split('=')
        yield {
            'name':name,
            'calc_dep': ['get_dep:%s' % formula],
            'actions': [(evaluate, (name, formula))],
            }

Por ejemplo, nuestra A1 depende de A3 y A2 que no dependen de nada. Para parsear esto, usé el módulo tokenize, y tomo nota de cuales cosas son "nombres". Existen maneras más soisticadas ;-)

la función task_get_dep es una tarea de doit que crea tareas llamadas "get_dep:NOMBRE" para cada nombre de celda en cells.

A su vez, get_dep devuelve una lista de tareas de doit. Para nuestra celda A1, eso sería ["calculate:A2", "calculate:A3"] o sea que para poder calcular A1 primero tenemos que terminar esas tareas.

def get_dep(formula):
    """Given a formula, return the names of the cells referenced."""
    deps = {}
    try:
        for token in generate_tokens([formula].pop):
            if token[0] == 1:  # A variable
                deps[token[1]] = None
    except IndexError:
        # It's ok
        pass
    return {
        'result_dep': ['calculate:%s' % key for key in deps.keys()]
        }

def task_get_dep():
    for cell in cells:
        name, formula = cell.split('=')
        yield {
            'name': formula,
            'actions': [(get_dep, (formula,))],
            }

Y eso es todo. Veámoslo en acción. Podés obtener tu propia copia acá y probarlo instalando doit, editando cells y usándolo así:

ralsina@perdido:~/dosheet$ doit -v2 calculate:A3
.  get_dep:4
{}
.  calculate:A3
A3 = 4
ralsina@perdido:~/dosheet$ doit -v2 calculate:A2
.  get_dep:2
{}
.  calculate:A2
A2 = 2
ralsina@perdido:~/dosheet$ doit -v2 calculate:A1
.  get_dep:A3+A2
{'A3': None, 'A2': None}
.  get_dep:4
{}
.  calculate:A3
A3 = 4
.  get_dep:2
{}
.  calculate:A2
A2 = 2
.  calculate:A1
A1 = 6

Co­mo po­dés ve­r, siem­pre ha­ce el mí­ni­mo es­fuer­zo po­si­ble pa­ra cal­cu­lar el re­sul­ta­do de­sea­do. Si que­ré­s, hay al­gu­nas co­sas me­jo­ra­ble­s, que de­jo co­mo ejer­ci­cio pa­ra el lec­to­r. Por ejem­plo:

  1. Usar up­­to­­­da­­te pa­­ra no re­­ca­l­­cu­­lar de­­pen­­den­­cias inu­­ti­l­­men­­te.

  2. Eli­mi­nar la va­ria­ble glo­bal va­lues y usar los com­puted va­lues de doit en su lu­ga­r.

Acá es­tá el lis­ta­do com­ple­to, buen pro­ve­cho!

Tu Editor No Te Está Frenando

Mi­re­mos SLO­C, que es­tá des­acre­di­ta­da co­mo me­di­da de la pro­duc­ti­vi­dad de un pro­gra­ma­do­r, pe­ro se­gu­ra­men­te es una me­di­da ade­cua­da de lo que el pro­gra­ma­dor ti­pea.

Bue­no, las es­ti­ma­cio­nes de có­di­go to­tal pro­du­ci­do en la vi­da de un pro­duc­to son muy va­ria­bles (to­man­do las SLOC del pro­duc­to y di­vi­dien­do por la canti­dad de hom­bres/­día gas­ta­do­s), pe­ro sue­len os­ci­lar en­tre 10 y 100 SLOC por pro­gra­ma­dor por día. Sea­mos ge­ne­ro­sos y di­ga­mos 200.

En­ton­ces 200 lí­neas en 8 ho­ra­s. Eso es más o me­nos una lí­nea ca­da dos mi­nu­tos y la lí­nea pro­me­dio son unos 45 ca­rac­te­res. Asu­mien­do que sa­bés es­cri­bir al tac­to (y si no sa­bé­s, qué ver­güen­za), te pue­de lle­var 20 se­gun­do­s.

En­ton­ce­s, es­cri­bi­r, que es lo que mu­chos op­ti­mi­zan en su edi­to­r, lle­va me­nos del 15% de tu tiem­po. ¿Y cuán­to más rá­pi­do po­dés se­r? ¿Po­dés sa­car esa lí­nea en 10 se­gun­do­s? En­ton­ces aca­bás de li­be­rar el 8% de tu día. Y no creo que tu edi­tor te aho­rre la mi­tad del tiem­po de ti­pea­do.

¿Cuán­to tiem­po per­dés con los ojos flo­tan­do por los si­de­bar­s, los bo­to­nes, las tool­bar­s, etc?

En­ton­ces sí, ti­pear más rá­pi­do es una op­ti­mi­za­ció­n, pe­ro tal vez es pre­ma­tu­ra, por­que ¿Qué miérco­les es­ta­mos ha­cien­do el otro 80% del tiem­po? ¿No hay na­da que po­da­mos ha­cer pa­ra que ese pe­da­zo enor­me de tiem­po sea más efi­cien­te en vez del pe­da­zo chi­qui­to?

Creo que usa­mos gran par­te de ese tiem­po en tres co­sas:

  1. Leer có­­­di­­go

  2. Pen­sar qué có­­­di­­go es­­cri­­bir

  3. Arre­­glar el có­­­di­­go que es­­cri­­bi­­mos

la pri­me­ra es fá­ci­l, ne­ce­si­ta­mos me­jo­res lec­to­res no edi­to­res. Es una pe­na que la in­ter­fa­ce por de­fault pa­ra mi­rar có­di­go sea un edi­to­r, con su cons­tant in­vi­ta­ción a cam­biar lo que de­be­ría­mos es­tar ob­ser­van­do. Cre que hay una opor­tu­ni­dad per­di­da ahí, en al­gu­na par­te, de te­ner una apli­ca­ción en la que se pue­da ver el có­di­go de ma­ne­ras in­te­re­san­tes y ori­gi­na­la­es, pa­ra en­ten­der­lo me­jo­r.

La se­gun­da es más di­fí­ci­l, por­que es per­so­na­l. Yo ca­mino. Si me ves ca­mi­nan­do con el edi­tor abier­to, es­toy pen­san­do. Des­pués de que pien­so, es­cri­bo. A mí me sir­ve.

La ter­ce­ra es la más di­fí­ci­l. Sí, el au­to­com­ple­ta­do sir­ve por­que no te­nés tan­tos ty­po­s, pe­ro hay en­fo­ques más po­de­ro­so­s, co­mo co­rrer cons­tante­men­te test sui­tes mien­tras edi­tá­s. Ca­da vez que de­jás una lí­nea, lan­zar los tes­ts afec­ta­do­s.

Eso es su­ma­men­te di­fí­cil de im­ple­men­tar por­que tus he­rra­mien­tas de­be­rían re­la­cio­nar tu sui­te de tes­ts con tu có­di­go muy pre­ci­sa­men­te, pa­ra que veas que rom­pis­te co­sas en el se­gun­do que las rom­pis­te, no un mi­nu­to des­pué­s.

Tam­bién se de­be­ría po­der sal­tar a los tes­ts con una te­cla, pa­ra que pue­das arre­glar los tes­ts si es­tás cam­bian­do com­por­ta­mien­to en tu có­di­go. Y por su­pues­to sig­ni­fi­ca que ne­ce­si­tás tes­ts ;-)

Lo que me trar a una co­sa que me pi­ca ha­ce mu­cho, que los edi­to­res tra­tan al ar­chi­vo co­mo uni­dad de tra­ba­jo, que no tie­ne mu­cho sen­ti­do. ¿Cuan­do tu­vis­te ga­nas de edi­tar un ar­chi­vo? ¡Nun­ca! Que­rés edi­tar una cla­se, una fun­ció­n, un mé­to­do, una cons­tan­te, no un ar­chi­vo. Sa­ber eso era el ge­nio del an­ti­guo Vi­sual Ba­si­c, ig­no­ra­do por to­dos los que lo mi­ran con­des­cen­dien­te­men­te.

Así que en vez de pa­vear con tu edi­to­r, ha­cé­me una he­rra­mien­ta que ha­ga lo que ne­ce­si­to, por fa­vo­r. La ven­go es­pe­ran­do des­de VB 1.0. Eso y un san­dwi­ch.

war­ning

Es­te post es 99% men­ti­ra­s, pe­ro me gus­ta­ría ver ar­gu­men­tos en contra. Si lo avi­so no es trai­ció­n, etc, etc. ;-)

UP­DA­TE: In­te­re­san­tes dis­cu­sio­nes en re­ddit y ha­cker news

Hack Para Catalogar Libros

import sys
import time
import gdata.books.service
import json

def get_book_info(isbn):
    print "Looking for ISBN:", isbn
    google_books = gdata.books.service.BookService()
    result = google_books.search('ISBN %s '%isbn)
    data = [x.to_dict() for x in result.entry]
    if not data:
        print "No results"
        return
    title = data[0]['title']
    with open(title+'.json','w') as f:
        f.write(json.dumps(data))
    print "Guardada info de '%s' en '%s.json'" %(isbn, title)

if __name__ == "__main__":
    while True:
        isbn = sys.stdin.readline().strip()
        if isbn:
            get_book_info(isbn)
        time.sleep(1)

¿Qué ha­ce? Lee nú­me­ros IS­BN y guar­da la da­ta del li­bro en "tí­tu­lo­.­j­so­n" pa­ra que des­pués lo pro­ce­ses y for­ma­tees.

Si que­rés edi­tar esa in­fo, po­dés usar un edi­tor de tex­to, o usar jso­nwi­dget y un po­co de as­tu­cia así:

python -c 'import jsonwidget; jsonwidget.run_editor("abook.json", schemafile="gbooks.schema")'

En ese co­man­do abook.­j­son es un ar­chi­vo ge­ne­ra­do por el script an­te­rio­r, y gbooks.­che­ma es es­te ar­chi­vo.

Ah, y si tus li­bros tie­nen có­di­gos de ba­rra...

zbarcam --raw | python bookdata.py

Le mos­trás los li­bros a la com­pu y ella ha­ce el res­to :-)

PD: es­ta­ría bue­ní­si­mo que al­guien hi­cie­ra una app de ca­tá­lo­go de li­bros con es­tas co­sas ;-)

El Post Largo de PyCamp

Py­Camp fué or­ga­ni­za­do por PyA­r, la co­mu­ni­dad de Py­thon Ar­gen­ti­na. PyAr es gen­te muy es­pe­cia­l, com­ple­ta­men­te ama­teu­r, y ha­cen to­do por amor y di­ver­sió­n. Ya que PyAr es gen­te es­pe­cia­l, las co­sas que PyAr ge­ne­ra, ins­pi­ra o crea son es­pe­cia­les tam­bién.

Así que des­de ha­ce al­gu­nos año­s, lo que pa­sa es que al­guien en­cuen­tra un lu­gar con cu­che­ta­s, un salón gran­de, ais­la­do, que sir­van co­mi­da­s, ba­ra­to (no es fá­cil to­do eso) y lo al­qui­la un fin de se­ma­na lar­go, y lo pa­ga­mos en­tre to­do­s.

Es­te año, un even­to de 4 día­s, all in­clu­si­ve, cos­tó 100 dó­la­res. Se­gu­ro, no es lu­jo­so, pe­ro te­nés un te­cho, y es­tás pro­te­gi­do de los ani­ma­les sal­va­je­s, qué más que­ré­s.

En­ton­ces ter­mi­nás con al­gu­nas do­ce­nas de ner­ds y sus com­pu­ta­do­ra­s, uno sa­be ar­mar re­des (Jo­ac!) uno es el MC (A­le­cu!) uno ayu­da a to­do el mun­do (Fa­cun­do­!) uno co­no­ce a los del lu­gar (Pin­don­ga!) y así, el tra­ba­jo se di­vi­de, y te­ne­mos tiem­po y com­pa­ñe­ros pa­ra ha­ckea­r.

En­ton­ce­s, la pri­me­ra ma­ña­na, to­dos pro­po­nen qué les gus­ta­ría ha­ce­r. Se vo­ta, y las pro­pues­tas con más vo­tos re­ci­ben slo­ts (5 al día) en que son el fo­co de aten­ció­n.

¿Qué pa­sa si tu pro­pues­ta no re­ci­be vo­to­s? Bue­no, o te unís a una que te gus­te, o ha­cés la tu­ya, por­que es­to no es una de­mo­cra­cia, es una anar­quía, los vo­tos son pa­ra que to­dos se­pan que van a ha­cer los de­más no­má­s, y en­con­trar un gru­po con el que te pue­das di­ver­tir (es muy pa­re­ci­do a una co­sa que pa­sa en "The Dis­po­ssess­e­d" de Le­Gui­n, ya que es­ta­mo­s)

Des­pué­s, ha­cés lo que quie­ra­s. O te po­nés los au­ri­cu­la­res y pro­gra­má­s, o pa­seás y char­lás o te unís a un gru­po, o un po­co de ca­da co­sa. Co­mo te sir­ven la co­mi­da no te preo­cu­pás de cuan­do cor­tá­s. Cuan­do la co­mi­da es­tá, to­do el mun­do cor­ta al mis­mo tiem­po y se va a so­cia­li­zar a me­sas co­mu­ni­ta­ria­s.

¿Sue­na ra­ro, no? Un mon­tón de gen­te gran­de, mu­chos pro­fe­sio­na­le­s, ha­cién­do­se los hi­ppie­s. ¡Bue­no, tam­bién se sien­te ex­tra­ño, pe­ro no quie­re de­cir que no es­té bue­no! Has­ta fun­cio­na bien. Una vez que ves a los otros tra­ba­jan­do, te em­pie­zan a pa­re­cer di­ver­ti­das co­sas que no es­pe­ra­rías (Ce­le­r­y!?! Ju­gger­nau­t! An­droi­d!) y la adre­na­li­na de ver gen­te di­cien­do­te "mi­rá lo que hi­ce" es in­fec­cio­so y exi­tan­te.

Ade­má­s, au­tos a con­trol re­mo­to, ha­cking una ki­nec­t, an­droi­d, gui­ta­rra eléc­tri­ca, ma­la­ba­res, lec­cio­nes de mo­no­ci­clo, fo­gó­n, al­coho­l, ca­fé ma­te, jue­gos de me­sa, car­ta­s, mú­si­ca, bro­ma­s, adre­na­li­na, ara­ño­ta­s, asa­do, frío, vi­m, nin­ja, ping pon­g, na­ves ro­bo­t, gen­te que ves ca­da seis me­s­es, pre­gun­ta­s, no sa­be­r, ave­ri­gua­r, que te ayu­den en al­go que lle­vás se­ma­nas tra­ba­do, des­tra­bar a otro, sen­tir­te bu­da y un bo­lu­do en cin­co mi­nu­tos ...

Y por lo me­nos yo, por lo me­nos es­te año, tu­ve un fin de se­ma­na pro­duc­ti­vo. Me ayu­dó un mon­tón de gen­te en co­sas que me da­ban mie­di­to, me sen­tí un pro­gra­ma­dor ac­ti­vo en vez de un ex, y la pa­sé bár­ba­ro. Me reí mu­cho, hi­ce un par de ami­gos nue­vo­s, vi un mon­tón de ami­gos vie­jo­s, ayu­dé a al­gu­no­s.

Me en­can­ta­ría que otros la pa­sen tan bien co­mo la pa­sé yo. Por su­pues­to que no creo que to­dos ten­gan que ir, si no es­tás en Ar­gen­ti­na es un via­je ca­ro, si no ha­blás es­pa­ñol te per­dés mu­cho, y si se jun­ta de­ma­sia­da gen­te ca­paz que de­ja de ser di­ver­ti­do.

¿Pe­ro por qué no ha­cer al­go pa­re­ci­do? No tie­ne por qué ser so­bre Py­tho­n, pue­de ser so­bre har­dwa­re, chi­ches elec­tró­ni­co­s, pro­gra­ma­ción en ge­ne­ra­l, lo que sea, con­se­guí­te un lu­gar más o me­nos có­mo­do, más o me­nos ais­la­do, con un ca­te­ring ra­zo­na­ble, y tus 50 geeks más ami­go­s, y di­vertí­te.

Ca­paz que sa­le al­go útil tam­bién.


Contents © 2000-2020 Roberto Alsina