Dagens bugg

Följande kod, djupt nere i innanmätet på lagen.nu 1.0-koden, har en
bugg, som stått orättad i över tre år (det den ska göra är att stoppa in ett ’|’-tecken innan ändelser i
stil med ’lagen’, ’balken’, osv — dvs ’upphovsrättslagen’ ska bli
’upphovsrätts|lagen’ — detta av
EBNF-tekniska skäl
.

fixedindata = re.sub(r'\B(lagens?|balkens?|förordningens?)\b',
                     r'|\1', self.indata)

Hittar ni felet? Ledtråd — det uppträder bara för en av de tio
balkarna, samt för ett mycket litet fåtal lagar och förordningar.

”För mycket kunskap är en tung börda”

Ovanstående citat är antingen det mest korkade eller det mest insiktsfulla jag
kläckt ur mig på länge. Det jag tänkte på var att hur komplext ett
område kan kännas när man lärt sig mycket om det, och mer specifikt
var det i kontexten av mitt eget efterforskande kring legalt skydd för
tekniska skyddsåtgärder
.

Samtidigt diskuterade jag Unicode idag, ett ämne av ungefär samma
komplexitet, där det känns som jag kommit över backkrönet och hittat
the zen of unicode. Resan har varit ungefär såhär:

I början: ”Om man använder typ WideCharToMultiByte
för att spara som UTF-8 så funkar det med
alla tecken”

I mitten: ”Fast UTF-8 löser bara transportproblemet och får inte
förväxlas med riktiga strängar, samt att man måste räkna med att
bytearrayn kan bli sex gånger så lång som antalet bokstäver, och så
måste man tänka på att en 16-bitars widechar bara kan representera
Basic multilingual
plane
och unicodedatabasen är för stor att ha i
möblerade rum
och att om man ska jämföra strängar så måste
man se till att de är normaliserade först och tänk på att Ruby inte
har unicodesträngar eftersom japaner i allmänhet tycker att det där
med Han
unification
är ett problem och även om Tengwar kanske kommer med i
nästa version så finns det nog inte glyfer i din font för det
och…. GAAAAAH, ge mig swascii istället!”

I slutet: ”Det finns codepoints
i NFC. Allt annat är bara skuggor
på väggarna

Nu har jag iofs lärt mig mindre om Unicode än vad någon som Tim Bray har hunnit glömma bort, men
just nu känns det som komplexiteten på det området är borta — alla
bollarna som var i luften har nu landat, och jag kan lösa alla
teckenuppsättningsproblem som kommer i min väg (FLW…).
Och det var väl det som var poängen — innan man kommer över krönet är
kunskapen en tung börda (jfr ”ju mer man vet, desto mer
förstår man hur mycket man inte vet”).

Så, för att jämföra med min insikt i skydd för tekniska skyddsåtgärder:

I början: ”Man får typ inte knäcka kopieringsskydd längre för det har
WIPO bestämt

I mitten: ”Fast frågan är vad som är en effektiv teknisk åtgärd i
lagens mening, med tanke på att en teknisk åtgärd aldrig kan vara 100%
effektiv i teknisk mening, och innebär det faktum att temporära kopior
är upphovsrättsligt relevanta och kräver upphovsrättsinnehavarens
samtycke att det har uppstått en de facto åtkomsträttighet vid sidan
av exemplarframställningsrättigheter och spridningsrättigheter, och är
det i så fall en del av upphovsrätten eller är det fråga om
paracopyright, och vad innebär artikel 11:s begränsning till ”their
rights under this treaty” för möjligheten att kringgå tekniska
åtgärder inom ramen för upphovsrättsinskränkningarna och varför är
listan i infosoc artikel 6(4) 4 st. över inskränkningar som kan ges
företräde bara tillämpliga på fysiska exemplar och varför är förbudet
mot kringgåendeverktyg kopplat till att det ska finnas en
ekonomisk marknad för legala användningsområden och… GAAAAH,
skriv om upphovsrättslagen i
Prolog
istället!”

I slutet: … jag vet inte riktigt. Jag hoppas på att hitta the zen of
skydd för tekniska åtgärder innan den 3:e oktober. Vi får väl se hur
det går.

Unicode och python

UnicodeDecodeError: 'ascii' codec can't decode byte 0x84 in position 1: ordinal not in range(128)

Om du programmerat python känner du säkert igen ovanstående felmeddelande. Roten av problemet är att python har två strängtyper; den ursprungliga str som innehåller en singlebytesträng utan någon vidare information om vilken teckenkodning som använts, och unicode, som är en fullständig unicodesträngtyp.

Det faktum att båda dessa typer finns, fungerar och ser nästan likadana ut gör att en pythonprogrammerare måste vara på tårna hela tiden för att vara säker på vad för sorts data han bollar med — något som tar bort mycket av fördelarna med dynamismen i språket. Annars blir det lätt så att kod som verkar fungerande helt plötsligt krashar om någon stoppar in ett åttabitarstecken nånstans där ingen hade tänkt på att kunde göra det. Och om man inte är disciplinerad är det lätt att man snärjer in sig i en röra av unicode(…) och foo.encode(’iso-8859-1’). [1]

För lagen.nu 2.0-koden försöker jag använda unicode rakt igenom, så mycket som möjligt, och behandla str som om det vore en bytearray. Det går …sådär. ElementTree ger alltid ifrån sig unicode och man mår bäst om man bara stoppar in unicode i den (även om det går att stoppa in str, men det är inte att rekommendera att använda något med höga bitten satt). BeautifulSoup är unicode-only från och med version 3, vilket är ett stort steg framåt.

Django är dock ett sorgebarn i sammanhanget. Gränssnitten både utåt, mot webbläsaren och innåt, mot databasen, är str, dessutom utf-8-kodat (om man inte ändrat DEFAULT_CHARSET, vilket dock inte är en egentlig lösning), något som är det sämsta av bägge världar. Jag menar, len av en sträng som innehåller ’räksmörgås’ ska vara 10, aldrig 13, men kolla vad len(u’räksmörgås’.encode(’utf-8’)) är.

Vad värre är, det går inte att stoppa in unicode överallt heller. De modeller man skapar behöver få sina strängvärden som utf-8-kodade str, annars får man 'Warning: Data truncated for column 'subject' at row 1' och frågetecken i databasen. Åtminstone mot min MySQL-databas, som internt lagrar i utf-8 (tror jag). Är det likadant vad gäller Postgres och SQLite? Vem vet?

Det går väl att lära sig leva med. Sätt upp en barriär mellan django-land och min egen kod, och se till att all str-data kodas om till unicode, och vice versa. Det kanske ordnas innan 1.0, men det är mycket att göra.

Django är dessvärre inte ensam i detta — igår tillbringade jag alldeles för lång tid på att försöka använda email-modulen med unicodesträngar, men den modulen är inte unicodesäker. Simpleparse klarar inte heller unicodeindata. Det finns säkert fler exempel.

Just unicodehantering[2] är ett av de få områdena där jag saknar COM/CLR/Java-världen. Jag menar, multibytetecken funkade smärtfritt i VB6 för typ en miljon år sedan.

På temat unicode saknade jag igår några bra teststrängar för att testa unicodedata med lite exotiskare tecken (allt över U+0255, typ) — utländska motsvarigheter till Räksmörgås, typ. Jag hittade inget direkt, men klistrade ihop något baserat på wikipedias förstasida:

Unicode/UTF-8-test

Som en added bonus innehåller den en hel del BiDi-tester med vad jag tror är korrekt rendering. Jag hade ingen aning om att det var ett så komplicerat ämne, men nu har jag lärt mig en ny HTML-tag. Det är inte varje dag!


[1] Så ser lagen.nu 1.0-koden ut. Ibland blir jag påmind om en kompis som förklarade hur han programmerar C: ”klagar kompilatorn så sätter jag dit en ’*’, om inte det hjälper byter jag ut den mot ett ’&'”

[2] Och till en mindre del debugging, även om det har ändrats sedan jag upptäckte Wing IDE

Macfilsystem och unicode

Jag är, om inte en varm förespråkare för svenska språket, så åtminstone militant förkämpe för våra svenska tecken. Att se ett filnamn som raksmorgas.txt eller en URL i stil med http://foo.com/overgangsbestammelser gör ont i mig. Så när jag började med etikettexperimentet ville jag naturligtvis bevara svenska tecken både utåt och inuti systemet.

Just nu ser det faktiskt inte så bra ut utåt, då det står http://lagen.nu/etikett/s%C3%A4rskiljningsf%C3%B6rm%C3%A5ga i webläsarens URL-rad när det borde stå http://lagen.nu/etikett/särskiljningsförmåga — en bieffekt av spännande UTF-8-problem på Win32-versionen av Apache, vilket jag kanske berättar mer om nån annan gång — men inåt är det ganska fint.

Eftersom allting som kan vara en statisk fil är det på lagen.nu så sparas naturligvis ovanstående websida som
index/tags/särskiljningsförmåga.html i filsystemet. Filsystemet är, i det här fallet, ett NTFS-filsystem. Jag gör hela genereringen av alla statiska sidor på en windowsmaskin, nämligen, eftersom det är det enda fartmonstret jag har hemma (och det tar ändå flera timmar). Sen, när allt är klart, rsync’ar jag över allt till den Mac OS X-maskin som driftar själva lagen.nu.

Och det var här nånstans problemen började. Att överföra ”särskiljningsförmåga.html” från Windows till MacOS X över SMB (den ”vanliga” fildelningen) gick utmärkt, men med rsync fick jag det obegripliga felmeddelandet ”invalid argument”.

Det visade sig att Mac OS X-filsystemet internt lagrar filnamn i ”Normalization form D” — en unicodevariant på att representera tecken genom, att i fallet för bokstaven ’ä’, först ange ’a’ följt av U+0308 aka COMBINING DIARESIS, dvs två fristående prickar, avsedda att kombineras med föregående tecken. Det är inte nödvändigtvis så tokigt — jag matar in ’ü’ på den här datorn genom att först trycka på ”två fristående prickar”-knappen, sedan ’u’, en snarlik tankeprocess. Men det verkar lite bakvänt att lagra saker på det viset i filsystemet. Det verkar riktigt bakvänt att inte ens tillåta API-anropen för att skapa filer att använda alla giltiga unicodetecken. Och det verkar urbota tokbakvänt att skeppa MacOS X med en rsync som inte kompenserar för det här — jag vet inte om rsync-protokollet stödjer en angivelse av teckenuppsättning för filnamn, men i brist på annat borde man väl anta UTF-8 eller åtminstone Latin-1. Jag menar, det funkar finfint med den samba som levereras med systemet, som sköter den vanliga fildelningen.

Men så är det, så vad gör man? Man skriver ett litet fulhack som transformerar
särskiljningsförmåga.html till särskiljningsförmaÌŠga.html (den UTF-8-kodade representationen av det Normalization Form D-omvandlade filnamnet, sett genom Latin-1-glasögon), rsyncar, problem solved!

Svenska tecken funkar utmärkt på MacOS X vanligtvis — ända tills man gör något som inte riktigt förutsetts. Exempel: skapa en fil räksmörgås.txt i Finder, byt sen till Terminalen och prova följande:

[staffan@minimac tmp]$ ls r*.txt
-rwxr--r--  1 staffan  staffan  10  4 Sep 17:28 ra??ksmo??rga??s.txt*

Ett utmärkt exempel på en läckande abstraktion.

Imorgon ska jag tala om hur man inte ska designa sina RSS-feeds. Jepp, även de måste designas, men kanske inte på det sätt man först tänker.

Veckans Del.icio.us-länkar

Den här veckans intressanta länkar, från del.icio.us/staffanmalmgren

Quickies of the day

Not much time for interesting posts of my own these days, busy
studying history for my final oral exam on Wednesday. Meanwhile,
here’s what interested me in the blogosphere today.

  • Interesting
    blog entry
    from Frederik Lundh on the role of Trackers in the
    Widget Construction Set
    for Python. I might need to write some GUI code soon, maybe this would
    be the way to go.
  • Aaron Wormus worries
    about the embedded database SQLite and bad security practises (Hint:
    Keep the SQLite database file OUT of the web root)
  • Brad Adams posts slides
    and demos
    from his BorCon presentation. I
    think Borland might have a winner on its hand with the next version of
    Delphi, since it seems it will allow both classic Win32 programming
    and .Net programming, filling the niche that VB left with
    VB.Net. There’s a lot of people that wants to write code that runs on
    machines without the .Net runtime, and currently the only Microsoft
    option for that is C++. At the same time, people want to have the
    opportunity to do .Net development as well. Delphi’s might be the best
    option for these people.
  • Sam Ruby notices some character set mismatch in a blog post from
    Cory
    Doctorow
    , and dissects it in great detail. Almost as required a
    reading as Joel Spolsky’s much linked developers
    guide to Unicode
    .
  • David Warnock suggests
    that python is a good language for teaching kids how to code. I’m
    wondering how good Squeak
    works for this, seemingly as it’s designed for this and similar
    purposes?
  • Edward W. Felten suggests,
    like Lessig
    did
    a few weeks ago, that online porn shold be labeled with an
    ”adultsonly” or ”porn” tag. I said
    it then, and I’ll say it again: Take a look at PICS, the w3c standard that’s
    designed precisely for this and similar problems. Maybe the problem is
    that there is no ”standard” rating vocabulary with
    definitions for ”porn” or ”adultsonly”. Or maybe it’s the fact that
    only XML standard geeks can understand that last document. I think
    PICS need an evangelist quick, or others will reimplement it,
    badly.