Wreszcie jest nowy transport GG

Od jakiegoś czasu do źródeł transportu GG włączona jest biblioteka libgadu
(na dostępnych pakietach z libgadu nie można polegać). W libgadu ostatnio
znaleziono poważne błędy, więc trzeba było ją uaktualnić. Przy tej okazji
zajrzałem do kodu transportu GG… i wreszcie się porządnie za niego zabrałem,
co w rezultacie dało dzisiejsze
wydanie wersji 2.2.0
.

Od wersji 2.1.0 zmieniło się wiele. Większość jeszcze w lutym. Najważniejsze
zmiany to:

  • Wspomniane już włączenie libgadu do źródeł transportu.
  • Ignorowanie wybranych numerków.
  • Ustawianie osobnych statusów dla GG, można też ustawić specjalny status
    używany podczas niedostępności i niewidzialności.
  • Wywalenie całkiem zmiany haseł. Stary kod i tak nie działał z nowym
    protokołem (wymagającym czytania kodów z obrazków), a nowy protokół byłby
    dość niepraktyczny w implementacji.
  • Kupa różnych poprawek.
  • I chyba najważniejsze: obsługa subskrypcji obecności per-kontakt. Teraz
    powinny działać listy prywatności, ustawianie online/offline dla konkretnych użytkowników,
    jednokierunkowe subskrypcje (ja go widzę, a on mnie nie) itp.

Z ostatnim punktem związana jest pewna niedogodność: po upgrade’zie
użytkownicy będą musieli potwierdzić autoryzację dla każdego swojego
kontaktu z GG. To może być bardzo dużo klikania. Użytkownicy niektórych
serwerów mają już to za sobą, więc dobrze wiedzą o co chodzi.

Z poprawek wspomnieć mogę np. rezygnację z używania
GIOChannel
do czegoś, do czego się zupełnie nie nadają (śledzenie aktywności na sockecie obsługiwanym
przez coś innego niż GLib), czy wywalenie zupełnie niepotrzebnego (a pełnego
błędów) buforowania danych zapisywanych do strumienia XMPP. Ta druga zmiana
podobno spowodowała znacznie zmniejszenie obciążenia w dużych (tysiące zarejestrowanych użytkowników)
instalacjach transportu. A to buforowanie miało niby być optymalizacją… Poza
tym usunąłem ileś memleaków i innych błędów wykrytych przez Valgrinda.

Wersja
z wczorajszego wieczora już podobno całkiem stabilnie działała, a ja mam
nadzieję, że dzisiaj nie tylko poprawiłem kilka kolejnych błędów, ale i nie
wprowadziłem żadnych nowych. Jednak, jak znam życie, to pewnie za chwilę
dostanę parę bugreportów dotyczących jakiś nowych (a może i starych)
i strasznie głupich błędów. Jeśli tak, to postaram się szybko wydać poprawioną
wersję, jeśli nie, to pewnie kolejne wydanie będzie za jakiś rok albo i później.

Coś dla nieprzekonanych do dynamicznego typowania

Natrafiłem dzisiaj na artykuł Bruce’a Eckela

Strong Typing vs. Strong Testing
. Autor, znawca języków programowania,
znany autorytet w tej dziedzinie (autor słynnej książki Thinking in
Java
), opisuje w nim jak przekonał się do dynamicznego typowania
mimo, że wcześniej za jedyne słuszne uznawał statyczne systemy typów.
Oczywiście język z dynamicznym typowaniem, którym się zachwyca, to Python.
Interesująca jest też kontynuacja
tematu
— odpowiedź na list profesora, który z poprzednim artykułem
się nie zgadza. Blog Bruce’a
Eckela
dodałem do linkowni — czuję, że będę tam często zaglądał.

Miłe jest, że do Pythona przekonuje się coraz więcej znawców poważnych
języków
i miłe jest, że potrafią opisać czemu Python jest taki dobry
— zawsze to kolejne argumenty do przekonania nieprzekonanych. Co do
statycznego typowania, to też nie uważam tego za coś niezbędnego, ale raczej, że
w większości przypadków przeszkadza, jednak nie jestem też przeciwnikiem
wprowadzenia takich, opcjonalnych oczywiście, rozszerzeń do Pythona. Dobrze
czasem jest mieć możliwość zaznaczyć w kodzie dla jakich argumentów jest on
przygotowany. Często jest to istotna informacja dla innych developerów (ale tu
wystarcza odpowiednia dokumentacja) i dla interpretera/kompilatora (pozwala na
lepszą optymalizację krytycznych elementów kodu). Problem polega na tym, żeby
wprowadzić to nie psując przejrzystości i elastyczności języka i aby nie było
to nadużywane.

PyXMPP — coraz poważniej

Zrobiłem w końcu stronę WWW dla
PyxMPP
. To dopiero początek, ale na jakiś czas powinno starczyć. Zacząłem
też robić zestawy testów jednostkowym (opartych o PyUnit — moduł
unittest) do testowania całości. Na pierwszy ogień poszło
pyxmpp.jabber.vcard do którego już jakieś testy były i trzeba
było je tylko przerobić na PyUnit i uzupełnić. Oczywiście wyszło parę błędów,
które poprawiłem. Później pyxmpp.jabber.disco, w którym chciałem
uzupełnić API, testy miały mi pomóc zrobić to tak, żeby nic nie zepsuć.
Pomogły, a przy okazji poprawiłem w testowanym module sporo błędów. Ogólnie
fajna rzecz takie testy i wbrew pozorom nie tak bardzo upierdliwa (mniej niż
uzupełnianie docstringów).

Dzisiaj zrobiłem jeszcze małą rewolucję. Wkurzało mnie już to, że
importowanie jakiegokolwiek modułu z pyxmpp powodował
importowanie całości (prawie). Wynikało to z tego, że dla wygody developerów
pakiet pyxmpp importował najważniejsze obiekty ze swoich modułów.
Od dłuższego czasu głowiłem się na tym, jak to rozwiązań nie tracąc tej wygody
i nie psując za bardzo kompatybilności wstecz i w końcu coś wymyśliłem. Teraz
samo z siebie nic niepotrzebnie się nie importuje, ale jak ktoś chce po
staremu, to wystarczy że raz sobie zaimportuje pyxmpp.all, i/lub
pyxmpp.jabber.all albo pyxmpp.jabber.all (jeśli
któregoś z nich używa). W ten sposób chyba i wilk syty i owca cała.

Następnie zabrałem się za CJC. Wkurzało mnie długie ładowanie konfiga, okazało
się, że to przez częste wywoływanie logging.debug()
wywaliłem i jest lepiej. Potem postanowiłem porawić pewnego upierdliwego i
często zgłaszanego buga — część wpisów w rosterze pojawiało się przed
zamiast za nazwą grupy. Okazało się, że porównywanie JIDów z innymi obiektami
było w PyXMPP spieprzone i niektóre JIDy były mniejsze od None. I
znowu testy jednostkowe się przydały, a zgłoszenie mogłem zamknąć.

I po cholerę to wszystko piszę? Nie wiem… może, żebyście wiedzieli jak
wygląda prawdziwie geekowski sylwester… Nie, żebym nie imprezował —
specjalnie z tej okazji mam tu colę (z cytrynką) i chipsy
;-).

Doczego to doszło…

… portuję PyXMPP na
Windows. To znaczy gościu mi pisze co mu nie działa, a ja poprawiam. Wczoraj
wymieniłem swój resolver (który nie umiał znaleźć serwerów nazw na Windows) na
dnspython. Dzisiaj poprawiłem
streambase, żeby na sockecie używało recv() zamiast
read (Windows sucks, POSIX rulez! ;-)). I podobno
zadziałało.

Oprócz tego pracuję nad dokumentacją. Docstringi są już w całym kodzie,
HTML jakiś się z tego generuje. Właśnie kończę skrypt tworzący z drzewa
dokumentacji wyciągniętego przez epydoc plik XMI, który mogę
załadować do Umbrello aby narysować diagramy UML. Jeszcze tylko stworzyć
stronę WWW z tym wszystkim i może wreszcie jacyś developerzy się tym PyXMPP
zainteresują i ostatecznie pogrążę XMPPPY (konkurencję) ;-).

Znalezione na PubSub…

Pisałem już o swoich eksperymentach z PubSub. Zauważyłem, że jeden tytuł ciągle się
w powiadomieniach przewijał (z różnych źródeł): Python Is Not Java. W pewnym momencie dostałem
to nawet cyrylicą. W sumie to interesujące jak się informacja rozchodzi po różnych blogach itp.
W końcu postanowiłem zajrzeć o co chodzi i chyba znalazłem źródło: Python Is Not Java. Rzeczywiście
— ciekawy artykuł. Nie używam, ani za bardzo nie znam Javy, ale miło
poczytać chociażby o przewadze Pythona w niektórych dziedzinach
:-).

Zauważyłem też, że PubSub daleko do śledzenia całego Internetu, a może nawet
oni filtrują (cenzurują, jeśli ktoś woli) częściowo swoje feedy. Utworzyłem sobie subskrypcję która
miała wyłapywać różne erotyczne artykuły (taki eksperyment), ale nic takiego
się nie złapało (chociaż trafień zapytanie trochę miało). Możliwe też, że po
prostu brak feedów RSS dla takich mało ambitnych treści. BTW. wpisywanie zapytania fuck
ma mały sens — w końcu to wildcard do którego wszelkie tematy pasują ;-)

Mam go! :-)

Od wielu miesięcy gnębi mnie jeden błąd w CJC: czasem gdy ja coś robię (np.
przełączam bufory) i jednocześnie coś przychodzi z sieci to się wiesza. Typowe
zakleszczenie (deadlock). Wiadomo, że gdzieś źle blokady wątków zastosowałem,
ale to się strasznie źle debuguje (dlatego IMHO wątków należy unikać jak
ognia). Kiedyś próbowałem, ale bardzo się nie postarałem i poległem. Potem po
prostu problem olewałem (pojawiał się tylko raz na jakiś czas, więc można było
z tym żyć). Wczoraj powiesiło się znowu i postanowiłem dzisiaj coś z tym
zrobić.

Najpierw więc dodałem do CJC obsługę pliku konfiguracyjnego dla modułu
logging ze biblioteki pythona (świetna rzecz!). Potem zapuściłem
na źródłach coś takiego:


find . -name "*.py" | xargs perl -pi -e \
's/^(\s+)([\w.]+\.(acquire|release)\(\))[ \t]*$/\1logging.getLogger("lockdebug").debug("\2..."); \2; logging.getLogger("lockdebug").debug("...\2")/'

Po tej operacji odpaliłem CJC, wszedłem na dwa czaty grupowe i zacząłem
przełączać bufory jak szalony. Po jakiejś minucie, czy dwóch zwiesił się
(Murphy poszedł na piwo?). No i chyba mam go! 🙂


2004-10-24 16:49:38,503 window.py: 167 th#16386 DEBUG self.screen.lock.acquire()...
2004-10-24 16:49:38,516 window.py: 167 th#16386 DEBUG ...self.screen.lock.acquire()
2004-10-24 16:49:38,524 text_buffer.py: 42 th#65540 DEBUG self.lock.acquire()...
2004-10-24 16:49:38,525 text_buffer.py: 42 th#65540 DEBUG ...self.lock.acquire()
2004-10-24 16:49:38,526 window.py: 252 th#65540 DEBUG self.screen.lock.acquire()...
2004-10-24 16:49:38,527 text_buffer.py: 208 th#16386 DEBUG self.lock.acquire()...

Teraz pozostaje to poprawić i liczyć na to, że to odosobniony przypadek
:-)

Staczam się… ;-)

Chyba się staczam… ostatnio zarywam noce kodując w… PHP. ;-)

Wszystko dlatego, że postanowiłem u siebie postawić
system śledzenia błędów dla PLD. Stary był brzydki i
niezbyt wygodny, a przez ostatnie tygodnie nie działał w ogóle — zbytnio
obciążał maszynę na której był postawiony, a poprawiać go nie było komu.

Dyskusja na temat alternatywy powracała już kilka razy na listy zwykle bez
efektu. Jednak pewną tendencję w dyskusjach można było zauważyć — nowy
system powinien być opary o jakieś gotowe rozwiązanie, najlepiej żeby to była
Bugzilla, Mantis lub Flyspray. Bugzilla mi się nie podoba (stanowczo za dużo
kontrolek w formularzach), poza tym wydaje się na tyle skomplikowana, że jej
dostosowanie do naszych potrzeb mogłoby okazać się trudne i długotrwałem.
Mantisa nie znam, a Flyspray, znany
z Buggera po prostu mi się podoba,
a skoro ja użyczam sprzętu i chcę sie tym zająć, to moje zdanie może być
decydujące. :-)

Tak po prostu postawić Flyspray’a to byłoby za mało. On powstał dla
zupełnie innych projektów niż PLD. Np. pole system operacyjny nie ma
u nas sensu, zamiast tego ważniejsza jest architektura. Poza tym w błędzie
najistotniejszy jest pakiet którego dotyczy i jego wersja. Nie chciałem dla
każdego pakietu robić osobnego projektu (osobne projekty są dla poszczególnych
linii dystrybucji (Ra, Ac, Th) i innych projektów związanych z PLD (ten BTS,
LiveCD, RescueCD)), więc wykorzystałem obecne już pole kategoria.
Trzeba było przy tym mocno zmienić interfejs, gdyż pole wyboru pakietu
zawierające listę wszystkich pakietów (tysiące!) to byłoby nieużywalne.
Podobnie z wersjami, które w oryginalnym Flyspray są określane per-projekt,
a u nas muszą być per-pakiet. To wszystko udało się właściwie zrobić.
Udało mi się też przenieść bazę pluskiew ze starego systemu.

Poza zmianami przystosowawczymi wprowadziłem też inne ulepszenia.
Np. język interfejsu jest konfigurowalny per-użytkownik, a domyślnie brany
z ustawień przeglądarki. Poza tym włączyłem serwowanie stron jak
application/xhtml+xml dla przeglądarek które to akceptują. To
zresztą uziemiło system na jakiś czas, bo się okazało, że XHTML to strony
generowane przez Flyspraya mają tylko w DOCTYPE. No na głównej stronie nie
było źle, nie walidowała się jedynie z powodu pustego <optgroup/>.
Niestety większość pozostałych stron nie była nawet well-formed XML
przez co przestała się w ogóle wyświetlać. Wczoraj udało mi się większość
z tego poprawić, więc już się wyświetla w przeglądarkach obsługujących XML,
ale raczej Valid XHTML Strict to w większości nie jest.

No i dzisiaj wreszcie udało mi się uruchomić narzędzie, które w poprawianiu
tego XHTMLa może mi pomóc:
HTML Validator dla Mozilli
. Polecam! Niestety to rozszerzenie w postaci
gotowej do zainstalowania dostępne jest jest jedynie dla Windowsów.
W Linuksowym Firefoksie instaluje się bez zająknięcia, ale po prostu nie
działa. Okazało się, że w środku siedzi binarka nstidy.dll,
nstidy.so trzeba sobie samemu skompilować (źródła rozszerzenia są
dostępne). Do kompilacji teoretycznie potrzebne są źródła Mozilli, ale nie
uśmiechało mi się ich instalowanie i kompilowanie, więc jakoś poradziłem sobie
bez tego — w końcu hacker jestem! ;-)

Poza BTSem podłubałem trochę w automatyce builderów (małe zlecenie do
Havnera). To już była czysta przyjemność, bo automatyka jest w Pythonie.
:-) Niestety okazało się, że przy okazji coś po psułem
i w niedzielę w nocy, zamiast iść spać musiałem poprawiać…

Rozpowszechnianie standardów…

Już pisałem o tym, że do generowania dokumentacji do PyXMPP używam
Epydoc. Bardzo ładnie wyciąga
dokumentację z kodu, ale… zajrzałem wczoraj do wygenerowanego HTMLa.
Najpierw miła niespodzianka, DOCTYPE XHTML 1.0 Transitional. Jednak
radość znikła gdy zapuściłem na tym xmllint --valid
--noout
. Nawet well-formed to nie było. xmllint
--html
nie lepiej. Ani o XHTML, ani HTML. Gdy zajrzałem do środka
moje obawy się potwierdziły — koszmarek. Wstyd mi by było to na stronie
projektu publikować.

Wczoraj więc wypełniłem bugreporta na SourceForge, a
dzisiaj w tym podłubałem i conieco porawiłem. Już się waliduje, niestety nie
jako XHTML Strict, bo to ramek używa. Ale i tak usunąłem wszystkie
<center/>,
<font/>,
<b/>,
<i/>, itp.,
zamieniając na coś odpowiedniejszego i dodając odpowiedni styl. Poprawiłem
też funkcję kolorującą regexpy (w dokumentacji pyxmpp.jid wrzucała znak bajt 0
do wyniku) oraz obcinającą za długie fragmenty HTMLu (żeby zamykała tagi).
Patcha dołączyłem do bugreportu i opisałem na liście dyskusyjnej. Zobaczymy co
z tego wyniknie ;-). Mam nadzięję, że patch nie zostanie olany.

Coś nie tak z resolverem…

Już jakiś czas temu ktoś miał problemy z CJC, które nie łączyło się z tym co
trzeba, czy nie mogło znaleźć serwera. Pomyślałem, że to mój resolver nawala,
ale user który to zgłosił stwierdził, że miał bzdury w swojej konfiguracji
(/etc/resolv.conf).

Dzisiaj dwóch (a może jeden wczoraj, nie pamiętam) użytkowników zgłosiło mi,
że CJC zwraca błąd, że serwer odrzucił połączenie. Poprosiłem o logi i w
jednym z tych logów jak byk było, że CJC szuka
jabber.bnet.pl, a potem łączy się z
209.73.243.23, który to adres IP nie ma nic z
jabber.bnet.pl wspólnego. Drugi user w logach nie miał nic na ten
temat (nie wiem czemu), ale zaczęło mu działać dopiero po podaniu adresu IP
serwera w konfiguracji CJC.

Czyli jakiś błąd ewidentnie jest, ale ja nie wiem jak go szukać. Bo oczywiście
u mnie działa.