Django: pluralize

Naj­waż­niej­szą rze­czą, jaką powin­ni­ście wie­dzieć na temat fil­tra pluralize jest ta, żeby go nigdy nie uży­wać. Nigdy. Jego ist­nie­nie wynika z leni­stwa ludzi, któ­rzy nigdy w życiu nie przy­go­to­wy­wali apli­ka­cji do tłu­ma­cze­nia. Jeśli nie wyra­zi­łem się dość jasno, uży­wa­nie fil­tra pluralize wywoła u cie­bie raka, ste­reo­po­roże i zatwar­dze­nie rozsiane.

Jak­kol­wiek spryt­nie by nie wyglą­dał, ten kod nie nadaje się do niczego:

<p>
    There {{ item_count|pluralize:"is,are" }}
    {{ item_count }} thing{{ item_count|pluralize:"s" }}.
</p>

Dla­czego się nie nadaje? Spró­buj­cie go prze­tłu­ma­czyć na kilka języ­ków. Nie­któ­rzy chwy­tają się brzyd­kich obejść, inni wolą zro­bić to zgod­nie ze sztuką. Jeśli kie­dy­kol­wiek pra­co­wa­li­ście przy loka­li­za­cji opro­gra­mo­wa­nia, dosko­nale wie­cie, że tłu­ma­cze­nie jed­nego słowa jest tak samo sen­sowne, jak tłu­ma­cze­nie każ­dej litery z osobna.

Poprawna wer­sja jest przy oka­zji czytelna:

<p>
{% blocktrans count item_count as items %}
    There is {{ items }} thing.
{% plural %}
    There are {{ items }} things.
{% endblocktrans %}
</p>

{% blocktrans %} z {% plural %} uży­wają ungettext, dzięki czemu bez koniecz­no­ści odpra­wia­nia cza­rów radzą sobie z pol­skimi liczeb­ni­kami (jeden tysiąc, dwa tysiące, pięć tysięcy).

Python: alternatywa dla dict.update

Kolejny skrót. Dość regu­larny przy­pa­dek zwró­ce­nia sumy słow­ni­ków bez nisz­cze­nia któ­re­go­kol­wiek z nich:

def foo(bar, baz):
    tmpdict = dict(bar)
    tmpdict.update(baz)
    return tmpdict

Można rów­nież roz­wią­zać ina­czej, korzy­sta­jąc z faktu, że dict akcep­tuje nazwane parametry:

def foo(bar, baz):
    return dict(bar, **baz)

Korzy­sta­jąc ze skró­tów zawsze upew­nij się, że na pierw­szy rzut oka wia­domo, co dany kod robi.

Django: direct_to_template

Nie wiem, czemu nie­któ­rzy tak upar­cie korzy­stają z funk­cji render_to_response, by za każ­dym razem prze­ka­zać do niej ręcz­nie stwo­rzony obiekt kon­tek­stu. Zresztą, sami oceń­cie, która wer­sja jest ładniejsza:

from django.shortcuts import render_to_response
from django.template import RequestContext

def foo(request):
    # ...
    return render_to_response('foo.html', {'bar': baz},
            context_instance=RequestContext(request))

Czy może:

from django.views.generic.simple import direct_to_template

def foo(request):
    # ...
    return direct_to_template(request, 'foo.html', {'bar': baz})

A teraz pomnóż­cie to przez liczbę wido­ków w aplikacji.

Python: prawdziwy polimorfizm

Taki week­en­dowy żarcik:

#!/usr/bin/env python
import random

class Foo(random.choice([int, str, unicode, Exception])):
    pass

f = Foo('1')
print `f`

O fontach raz jeszcze, czyli wielkość się liczy

Z powodu wystę­pu­ją­cego dzi­siaj u mnie prze­si­le­nia kataru, zosta­łem zmu­szony (dosłow­nie ze łzami w oczach) do zmiany wiel­ko­ści fon­tów z 10 na 12 punk­tów. Póź­niej wspo­mnia­łem o tym kilku oso­bom, doda­jąc, że nie roz­róż­niam liter poni­żej 16 pik­seli, co w dwóch przy­pad­kach wywo­łało kon­ster­na­cję. Punkty i pik­sele to nie to samo.

Punkt jest jed­nostką typo­gra­ficzną pocho­dzącą ze stan­dardu pica, który to stwo­rzyli Ame­ry­ka­nie by zemścić się za nasz sys­tem metryczny. Według stan­dardu okrą­głe¹ dwa­na­ście punk­tów (pt) równe jest tytu­ło­wemu pica (pc). Z kolei sześć pica równe jest jed­nemu calowi (in). Jak wiemy cal to 2,54 cen­ty­me­tra (cm), ale w tym przy­padku nie jest to wie­dza istotna.

¹ Tak, bez­czel­nie naśmie­wam się z sys­temu zbu­do­wa­nego na wie­lo­krot­no­ściach liczby 6.

Co wiemy do tej pory: 72pt = 6pc = 1in = 2.54cm = 25.4mm.

Na szczę­ście roz­dziel­czość sprzę­tową (DPI) rów­nież zde­fi­nio­wali Ame­ry­ka­nie i liczymy ją w punk­tach na cal. W punk­tach ekra­no­wych, czyli pik­se­lach (nie w punk­tach typo­gra­ficz­nych, o któ­rych mówi­li­śmy wcze­śniej). DPI jest para­me­trem kon­kret­nego ekranu² i mówi nam, ile kolej­nych pik­seli (px) ekranu należy zapa­lić, żeby dłu­gość powsta­łej linii wyno­siła dokład­nie jeden cal. Dla przy­kładu: roz­dziel­czość sprzę­towa mojego lap­topa wynosi 96 pik­seli na cal, a mojego tele­fonu 260 pik­seli na cal.

² Oczy­wi­ście zakła­da­jąc poprawną kon­fi­gu­ra­cję sys­temu ope­ra­cyj­nego, nic nie stoi bowiem na prze­szko­dzie do wmó­wie­nia kom­pu­te­rowi, że jego ekran jest wiel­ko­ści biurka czy stadionu.

Posia­da­jąc tę wie­dzę, możemy zacząć prze­li­czać: 12pt = 12 × 1/72in = 12/72in × 96px/in = 16px. Voilà! Teraz mogę spo­koj­nie poumie­rać dalej.

Krzemowe kostki, czyli jak komputery zjadły RPG

Kiedy byli­śmy szczy­lami zupeł­nymi (pierw­sze dwie klasy pod­sta­wówki), zagry­wa­li­śmy się w Tali­zman, wtedy znany jedy­nie jako Magia i miecz. Gra wcią­gała, ale z cza­sem zaczę­li­śmy szu­kać odmiany. Advan­ced Dun­ge­ons & Dra­gons oka­zało się strza­łem w dzie­siątkę, przy­naj­mniej na jakiś czas.

Nie­długo póź­niej zaczę­li­śmy swoje pierw­sze eks­pe­ry­menty z poważ­nymi RPG. Eks­pe­ry­menty to dobre okre­śle­nie, bo pierw­sze spo­tka­nia dzie­się­cio­lat­ków z odbi­tym na ksero pod­ręcz­ni­kiem do War­ham­mera (po angiel­sku) były dość nieporadne.

Szybko jed­nak roz­krę­ci­li­śmy się na tyle, że gra­nie nie wyma­gało już posił­ko­wa­nia się słow­ni­kiem (jeśli cho­dzi o angiel­ski, to wszy­scy byli­śmy samo­ukami). W 1991 poja­wiły się kse­rówki z tłu­ma­cze­niem Cyber­punka 2020. Na jakiś czas War­ham­mer poszedł w odstawkę — przy­naj­mniej jeśli cho­dziło o gry fabu­larne, bo figurki do bitew­niaka sku­tecz­nie uszczu­plały skromne zasoby finan­sowe całej grupy.

Oczy­wi­ście gry­wa­li­śmy rów­nież na kom­pu­te­rze, ale ówcze­sne RPG dzie­liły się na te z fabułą (jak np. Kult) i na te z tabel­kami (jak Eye of the Behol­der). Nikomu wtedy nie przy­szło do głowy koja­rzyć role-play’u z paskiem doświadczenia.

W papie­rowe gry fabu­larne gra­li­śmy dużo i czę­sto, bo nie mie­li­śmy prak­tycz­nie żadnych obo­wiąz­ków. W naszym reper­tu­arze gościły kolejne sys­temy (Zew Cthulhu, Wam­pir: Maska­rada), było dobrze. Gdzieś w tam­tym cza­sie, na łamach pisma Magia i Miecz, poja­wił się dzi­wo­ląg, który według obec­nych stan­dar­dów ktoś nazwać mógłby kla­sycz­nym RPG: Krysz­tały Czasu. Po raz pierw­szy postać mistrza gry została spro­wa­dzona do roli kru­piera, który miał jedy­nie pil­no­wać, by akcje gra­czy były zgodne z odpo­wied­nimi tabel­kami. Po jed­nej sesji dali­śmy sobie spo­kój i wró­ci­li­śmy do tra­dy­cyj­nych systemów.

Nie­stety, pod koniec pod­sta­wówki grupa się roz­pa­dła i na jakiś czas szlag tra­fił gra­nie. Kolejną ekipę zna­la­złem dopiero rok póź­niej. Pogra­li­śmy razem nie­mal trzy lata, po czym nasze drogi się rozeszły.

W tym cza­sie kom­pu­te­rowe gry RPG poszły naprzód. Dia­blo stało się kamie­niem węgiel­nym gatunku hack&slash, jed­nak z grami fabu­lar­nymi nie łączyło go zbyt wiele. Za cio­sem poszły jed­nak genialny Fal­lout oraz Wrota Bal­dura, które wielu sta­wia za przy­kład RPG ide­al­nego. Ci ostatni chyba nie wie­dzą, że praw­dziwa perełka uka­zała się dopiero w roku kolej­nym. Mowa oczy­wi­ście o Pla­ne­scape: Tor­ment, który w cudow­nie odświe­ża­jący spo­sób zerwał z kla­sycz­nie poj­mo­wa­nym świa­tem fantasy.

Mijały lata, a mi coraz trud­niej było wró­cić do papie­ro­wych RPG. Zde­cy­do­wana więk­szość napo­tka­nych gra­czy zda­wała się trak­to­wać gry fabu­larne jak salo­nową wer­sję Dia­blo. Nie było już istotne, w jaki sys­tem gramy. Liczyło się to, żeby mieć wyso­kie wszyst­kie sta­ty­styki na kar­cie postaci. Nade­szły czasy, kiedy każdy rybak znał kung-fu, każdy chłop pisał w mini­mum trzech języ­kach, a naj­częst­szym pyta­niem do mistrza gry stało się kiedy będziemy zabi­jać potwory?

Innymi słowy histo­ria zato­czyła pełne koło. Papie­rowe RPG wró­ciło do mojego punktu wyj­ścia, czyli ADnD. Kom­pu­tery pozba­wiły RPG dwóch pierw­szych lite­rek, została sama gra. Gra w licy­to­wa­nie się na sta­ty­styki i dys­ku­to­wa­nie z mistrzem gry na temat tego, czy poziom 9 danej cechy ozna­cza już mega­za­je­bi­stość, czy może warto jesz­cze rzu­cić kostką.

Na szczę­ście nie­które histo­rie mają szczę­śliwe zakoń­cze­nia i za namową swo­jej wspa­nia­łej kobiety wra­cam powoli do gra­nia w środo­wi­sku gra­czy, któ­rzy cenią sobie rów­nież fabułę. Któ­rzy potra­fią rzuty kostką ogra­ni­czyć do abso­lut­nego mini­mum i pro­wa­dzić przy­gody w duchu pod­ręcz­nika, a nie trak­tu­jąc dosłow­nie każde jego zda­nie. Męczymy nawet Google Wave z Cie­płym i Zenem, pró­bu­jąc użyć go jako plat­formy do gra­nia. A nuż uda się wziąć odwet na kom­pu­te­rach? Jest nadzieja.

Intencją tej notki jest zapobieganie głupocie

Za VaGlą:

Uważ­nie śledzę Wasze opi­nie, komen­ta­rze, pyta­nia i wąt­pli­wo­ści. Zde­cy­do­wa­łem, że jesz­cze raz przyj­rzę się pro­jek­to­wa­nej usta­wie. Inten­cją mojego rządu jest zapo­bie­ga­nie wyko­rzy­sty­wa­nia Inter­netu do roz­po­wszech­nia­nia por­no­gra­fii dzie­cię­cej, oszustw finan­so­wych czy nie­le­gal­nych gier hazar­do­wych, a nie ogra­ni­cza­nie wol­no­ści w sieci. Spró­bujmy to razem pogo­dzić. W związku z tym zapra­szam Was do debaty, która odbę­dzie się w przy­szłym tygodniu.

List pre­miera do inter­nau­tów (wyróż­nie­nie moje)

Pytam się tedy, czy inten­cją rządu pana Tuska jest mord? Wszak nie zabro­nił on sprze­daży tasa­ków, pił, bejs­boli, szpi­kul­ców do lodu, noży, a nawet widel­ców. To nie do pomy­śle­nia, zupeł­nie jak gdy­by­śmy chcieli uła­twiać mor­der­com życie.

Zapy­tuję, czy inten­cją rządu pana Tuska jest może gwałt? Parki nie wykar­czo­wane, brak nakazu pale­nia świa­tła przez całą dobę, w apte­kach nadal sprze­dają pre­zer­wa­tywy, a w pobli­skim skle­pie widzia­łem spodnie z roz­por­kiem na suwak. To wszystko prze­cież oko­licz­no­ści mogące się przyczynić.

Roz­darty wobec tych obser­wa­cji, wąt­pię osta­tecz­nie, czy rząd pana Tuska pla­nuje prze­ciw­dzia­łać wła­ma­niom. Łomy nadal bez zezwo­le­nia, dora­bia­nie klu­czy dostępne dla ludu, a w Tesco sprze­dają dru­ciane wie­szaki. Mało tego, doży­li­śmy cza­sów, w któ­rych do kamie­nicy można wejść bez uprzed­niej rewi­zji osobistej.

Ludzie, czy wyście na łeb upadli?

Kolejny film: Avatar

Tak, to znów ten czas, kiedy wra­cam z kina. Tym razem, za namową wielu, uda­li­śmy się obej­rzeć kolejną ofiarę Jamesa Came­rona, czyli czło­wieka, który nie zro­bił dobrego filmu od cza­sów Obcego i Ter­mi­na­tora. Tak, wiem, że nie­któ­rym podo­bały się rów­nież jego póź­niej­sze dzieła, ale jakoś nigdy nie byłem fanem muzyki Celine Dion.

Żeby zaosz­czę­dzić czasu, zacznę od maru­dze­nia, a potem sobie pooglą­da­cie dla rów­no­wagi puchate kró­liczki w inter­ne­cie i świat znów sta­nie się piękny. Na począ­tek kwe­stia techniczna.

Dro­dzy fil­mowcy, oko ludz­kie samo dosko­nale radzi sobie z ogra­ni­cza­niem głębi ostro­ści. Rozu­miem, że nie stać was na pre­cy­zyjne ren­de­ro­wa­nie kilo­metr w głąb sceny, ale jeśli roz­myte jest 90% pierw­szego planu i do ostrego widze­nia konieczne jest sku­pie­nie się na nosie głów­nego boha­tera, to zamiast rewo­lu­cji zafun­do­wa­li­ście widzom pie­przony ból głowy.

Lep­sze efekty 3D mie­li­śmy na domo­wych pece­tach w 2004 roku. Za dowód niech posłuży fakt, że wtedy potra­fi­łem bez cie­nia migreny spę­dzić 24 godziny w tak zwa­nych shut­ter glas­ses przy par­tyjce Ope­ra­cji Fla­sh­po­int (z 2001 roku!). A zapew­niam, że prócz oku­la­rów powo­dów do migreny mie­li­śmy całą skrzynkę.

Co zaś się samej fabuły tyczy, naj­krót­sza recen­zja Ava­tara, jaką znam, to Poka­hon­tas w kosmo­sie. Coś w tym jest, mi jed­nak upar­cie koja­rzył się inny film:

Cała reszta to muzyka z Króla lwa czy innej Księgi dżun­gli oraz prze­mowy aż pro­szące się o łopo­czącą w tle flagę USA. Disney pełną gębą. Jeśli ktoś po wizy­cie w kinie spo­dzie­wał się rewo­lu­cji, to chyba po nie­świe­żym popcornie.

Django: szybszy SQLite do testów

Domyślna kon­fi­gu­ra­cja SQLite każe mu syn­chro­ni­zo­wać plik bazy po każ­dej ope­ra­cji. W środo­wi­skach testo­wych nie musimy się mar­twić o spój­ność danych w wypadku awa­rii, poni­żej zamiesz­czam więc bac­kend pozba­wiony zbęd­nego narzutu:

from django.db.backends.sqlite3.base import (
    DatabaseWrapper as Sqlite3Wrapper,
    DatabaseError,
    IntegrityError,
    DatabaseFeatures,
    DatabaseOperations,
)

class DatabaseWrapper(Sqlite3Wrapper):
    def _cursor(self):
        new_conn = self.connection is None
        cursor = super(DatabaseWrapper, self)._cursor()
        if new_conn:
            cursor.execute('PRAGMA synchronous=OFF')
        return cursor

W przy­padku pro­jektu, nad któ­rym wła­śnie pra­cu­jemy, czas prze­bu­do­wa­nia bazy od nowa na par­ty­cji XFS spadł z pół­to­rej minuty do pię­ciu sekund.

Sherlock House i doktor Wilson

Wła­śnie wró­ci­li­śmy z seansu naj­now­szego Hol­mesa. Wróć, Sher­locka. Zanim jed­nak zacznę tor­tu­ro­wać ofiarę — pre­zent dla zmo­to­ry­zo­wa­nych: tylko teraz razem z poniż­szym tek­stem otrzy­masz nowiut­kie spo­ilery. Czas pro­mo­cji ograniczony!

Zosta­li­ście ostrzeżeni.

Już od pierw­szych kilku minut filmu staje się jasne, że główny boha­ter nie ma nic wspól­nego z miłym panem w kra­cia­stej czapce, jakiego znamy. Ma za to cięty język, krótki zarost i współ­lo­ka­tora, z któ­rym robią sobie na złość, a któ­rego związki nisz­czy z lubo­ścią. Do tego nie radzi sobie z kobie­tami, pije i zamyka się w sobie, kiedy tylko zabrak­nie mu cie­ka­wych przy­pad­ków. Brzmi znajomo?

I tak pozo­staje przez cały film. Ale to jesz­cze nie koniec nowego image’u, bowiem skąd mia­łem wie­dzieć, że ten gość to jakiś cho­lerny cygań­ski Muham­mad Ali?

Nie, nie pomy­li­łem filmu.

Czy to zły film? Pew­nie nie. Czy to zły Hol­mes? To jest tra­giczny Hol­mes — spro­wa­dzony do postaci kolej­nego Indiany Jonesa. Wła­ści­wie to jest to wzo­rowy Indiana Jones. Źli dostają po ryjach, główny zły nosi płaszcz Gestapo, a w całym fil­mie nie ma ani śladu kosmity. Fanom powie­ści detek­ty­wi­stycz­nych pole­cam w zamian wypo­ży­czyć nie­do­ści­gniony dotąd Vidocq z 2001. roku.

Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland
This work by Patryk Zawadzki is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland.