Bye-bye, CVS

Miam na tyle dość CVS, że postanowiłem przenieść moje Jabberowe projekty
do Subversion. Okazało się to łatwiejsze niż przypuszczałem. Na JabberStudio
jest zainstalowany SVN, skonfigurowany svnserve, a nawet jakiś
ViewCVS do tego.

Wczoraj wieczorem przemigrowałem repo PyXMPP. Dodałem skrypt do generacji
ChangeLog (tym razem nie po stronie serwera) oraz automatykę do generowania
snapshotów — dla tych co uparcie bronią się przez SVN, a chcieli by
spróbować świeżego PyXMPP czy CJC.

Następne w kolejce jest oczywiście CJC, no i może Transport GG. Zobaczymy
co z tego wyniknie.

Nowy ejabberd

Niedawno wyszedł Ejabberd
0.7.5. Czekałem na niego, bo miał mieć StartTLS i ulepszony interfejs
administracyjny. Wczoraj zainstalowałem go na jabber.bnet.pl.
Przy okazji wyszły błędy (dotyczące AMD64, którego akurat używam na tym
serwerze) w paczce dla PLD.

I rzeczywiście, na stronie
administracyjnej pojawiła się opcja dodawania userów, a przy połączeniu
możliwość użycia StartTLS. To ostatnie objawiło się w CJC pięknym tracebackiem
i komunikatem błędu, że zły XML przyszedł. Na konsoli XML śmieci. Oczywiście
coś spieprzyłem przy ostatnim oczyszczaniu kodu. Nie miałem StartTLS na
serwerze, to nie zauważyłem.

Dzisiaj w pracy poprawiłem, wspomniane błędy w paczce ejabberd, a także
problemy w budowie erlanga na builderach. W oficjalnym Ac oba pakiety powinny
się niedługo pojawić. Wieczorem poprawiłem też obsługę StartTLS w PyXMPP i CJC
(oba trzeba było poprawić) i już mogę się cieszyć szyfrowanymi połączeniami z
serwerem. I to na normalnym porcie! :-)

Nie tak całkiem leniuchuję…

Postanowiłem przenieść listy dyskusyjne moich projektów z Enemies of
Carlotta
na mailmana. To pierwsze nie bardzo się
rozwija, a i możliwości ma skromne, a z mailmanem i tak się muszę męczyć przy
innych listach (przy okazji się przekonałem, że od strony administratora jest
nieco przyjemniejszy). No i nawet listy działają. Udało się to nawet pogodzić
z moją SQLową bazą użytkowników synchronizowaną na zapasowym MX. Jednak
stwierdzam, że mailman to gniot, szczególnie ten z paczki PLD
(której jednak nie chciało mi się poprawiać). A już zupełnie obsługa
wirtualnych domen dla postfixa (tak jak on to robi, to te domeny są średnio
wirtualne, bo listy zaśmiecają przestrzeń nazw systemowych użytkowników).
Ale przejście się chyba opłacało. Listy jak już ruszyły to działają, a archiwa
wyglądają lepiej.

Jakiś czas temu jeden z Release Managerów PLD prosił mnie, abym
dorobił ACLe na branche do automatyki builderów. Wczoraj więc się za to
zabrałem: cvs up, poprawka, login na src-builder (najważniejszy z
builderów), cvs up i sprawdzam jak to działa… W tym czasie inny
developer PLD mnie informuje, że jak robię te poprawki na HEAD, to to się na
nic nie zda, bo to co jest na HEAD i tak się na buildery nie nadaje, bo ów
developer coś tam samemu psocił. No fajnie, ale przecież właśnie to na głównym
builderze zainstalowałem…

Na szczęście psuja zostawił taga na ostatniej działającej wersji
automatyki. Z taga zrobiłem brancha, przeniosłem tam swoje poprawki i z tego
brancha zrobiłem cvs up na builderze. Jeszcze parę poprawek do
mojej poprawki i ACLe na branche działają :-). Mogłem wreszcie
pójść spać (0:30).

W przedpoprzednim wpisie, tam gdzie wspominałem o RFC 3920, 3921, 3922 i
3923, wspominałem, że dodam odwołania do tych RFC do dokumentacji PyXMPP.
Jednak dopiero przed chwilą mi się to udało, przez te zabawy z automatyką
builderów i listami dyskusyjnymi. Ale za to dopisałem też odwołania do
wszelkich innych implementowanych RFC i JEPów. Będzie łatwiej znaleźć
odpowiedni dokument jak będzie trzeba coś sprawdzić.

A jutro jadę na Jesień Linuksową
:-).

Mix-ins

Gdy w CJC użyłem osobnej klasy (nazwijmy ją A) do
rozszerzenia funkcjonalności innej klasy (B), ale tak, że to
B dziedziczyło po A, to myślałem że stosuję jakiś dziwny,
brudny trik dla własnej wygody. Później czytając dokumentację do
pylinta spotkałem się z określeniem mix-in class, nie
wiedziałem co to jest, ale tak jakoś mi się skojarzyło z tym co zrobiłem w
CJC.

Teraz coś podobnego chcę zrobić w PyXMPP, aby podzielić
jeden wielki moduł pyxmpp.stream na mniejsze kawałki.
Przypomniałem sobie o mix-in class i wrzuciłem to w Google. Okazało się,
że miałem rację. Dowiedziałem, że to znana technika programowania
obiektowego, która wcale nie jest zła. Znalazłem nawet artykuł o tym jak używać mix-ins w
Pythonie
. Rzeczywiście Python bardzo ułatwia stosowanie tej techniki.

No to teraz, gdy się podszkoliłem, mogę z czystym sumieniem wziąć się za
wydzielanie StreamSASLMixIn i StreamTLSMixIn.
:-)

No i stało się

Przed chwilą dokonałem zmian w PyXMPP w kierunku który doradził Jarek,
ostatecznie zrobiłem tak:

  • fr -> from_jid
  • to -> to_jid
  • typ -> stanza_type
  • sid -> stanza_id

Dla ułatwienia życia sobie, a także innym developerom używającym PyXMPP
(są tacy?) przygotowałem też skrypt poprawiający kod pythona używający starych
nazw. Mnie nawet ten skrypt nic nie popsuł.

A w pracy wkurzałem się na interfejs WWW zarządzania switchy DLink
i access-pointów Proxima. Chcę dać na zewnątrz (żebym miał w domu,
czy gdzieś w terenie) dostęp do tych urządzeń. Że urządzenia nie mają SSL, to
nie mogę tego po prostu przeroutować, więc robię to przez reverse-proxy na
Apache z mod_ssl. Pierwszy problem to bezwzględne linki na stronach tych
interfejsów. Ale to załatwia (teoretycznie) mod_proxy_html.
Tylko, że mod_proxy_html parsuje otrzymany HTML, poprawia co
trzeba i serializuje od nowa. Ale jak to ma działać na czymś co do HTMLa jest
tylko miejscami podobne (tak jest w przypadku Proxima — po prostu
koszmar)? No nie całkiem działa. Do przeglądarki dochodzi już poprawny HTML,
ale wyrażający nie całkiem to co autor miał na myśli. Miejscami prześwituje
kod JavaScript, inne rzeczy poprzestawiane itp. Z tym pewnie będę jeszcze
długo walczył.

mod_proxy_html poprawia też skrypty JavaScript w kodzie
HTML, robi to na głupa, ale jak się postarać, to można uzyskać ciekawe
efekty. Gorzej ze skryptami zewnętrznymi, w osobnych dokumentach. W przypadku
switchy nie jest niby źle, bo w zewnętrznych skryptach nie ma zaszytych
żadnych ścieżek, ale za to są serwowane jako text/html, a co za
tym idzie mod_proxy_html próbuje z nich robić poprawnego
HTMLa. No i taki skrypt po dodaniu <html><body> na początku
i po przetworzeniu tagów w środku nie bardzo chciał działać. Musiałem więc tak
skonfigurować mod_proxy_html, aby zajął się jedynie
dokumentami *.html.

Proximy za to mają zaszyte ścieżki w plikach *.js, jednak
serwowanych poprawnie, jako text/javascript.
mod_proxy_html w ogóle tego nie rusza, za to znalazłem
jeszcze mod_ext_filter (standardowa część Apache 2.x). Przy pomocy tego
moduliku można serwowane dokumenty przepuścić przez zewnętrzny program. A więc
przepuściłem przez seda i poprawiłem ścieżki gdzie trzeba.
Nawet zadziałało. Chyba tego samego modułu wraz z sedem, albo
jakimś mądrzejszym skryptem w
perlu/awku/pythonie będę
musiał użyć do tego paskudnego HTMLa z Proxima. To jest do zrobienia,
ale może być z tym kupa roboty i nie wiem czy się wcześniej nie poddam.

Czyszczenie PyXMPP

Najwyraźniej jest jakieś zainteresowanie moją pythonową biblioteką
XMPP. Ludzie (przynajmniej paru) chcą tego używać, ale wielu od razu się
zniechęca brakiem dokumentacji, inni po próbach zrozumienia o co w tym biega.
Nie dziwię się — kod zamotany jak rzadko, a dokumentacji praktycznie brak.
Bardziej dziwię się ludziom takim jak pete, czy Zgoda, którzy tego używają i nawet mnie
z tego powodu nie męczą. Jednak uznałem, że trzeba coś z tym zrobić…

Więc od paru dni zamiast dodawać nowe ficzery do CJC, poprawiać
w nim bugi, czy implementacje protokołów w PyXMPP to ślęczę nad kodem PyXMPP
i, terroryzowany przez pylinta czyszczę kod,
co jakiś czas robiąc: cvs commit -m "cleaning up...". Przy jakiś
czas coś psuję głupimi literówkami, albo zamierzonymi zmianami w API PyXMPP
(sorry developerzy), np. zamiana nazwy parametru konstruktora klasy Stanza
z type na typ, bo ta pierwsza nazwa zakrywała nazwę wbudowanej
funkcji. Jak już wspominałem większość marudzenia pylinta dotyczy braku
docstringów, a więc je dodawałem na bieżąco. Oczywiście nie
"", ale w miarę konkretną dokumentację, która się może jakiemuś
developerowi przydać. I tu wkracza Epydoc

Normalnie do przetwarzania dokumentacji w pythonie służy narzędzie
pydoc. Jednak jest ono głupie, bo traktuje docstringi jako
czysty tekst, bez formatowania czy hyperlinków. Taka dokumentacja jest mało
czytelna i niewygodna. Już jakiś czas temu szukałem informacji na temat
robienia porządnej dokumentacji do kodu Pythona i dowiedziałem się, że the
right way
to jest (lub raczej będzie) używanie w docstringsch reStructuredText.
Narzędzi do przetwarzania tego wtedy nie znalazłem (słabo szukałem, albo
jeszcze nie było), znalazłem tylko docutils które, między innymi,
takim narzędziem mają się stać, ale na razie umieją tylko parsować
reStructuredText i konwertować to do mądrzejszych formatów.
Mimo braku narzędzia do obróbki tego jednak już wtedy postanowiłem
reStructuredText używać. I nawet użyłem w tych skrawkach
dokumentacji które zdążyłem zrobić.

Teraz przy czyszczeniu kodu znowu szukałem narzędzia do generowania
dokumentacji z kodu. Tym razem znalazłem. Docutils wciąż nie
umieją wyciągać dokumentacji z kodu Pythona, ale mogą być wykorzystane
przez Epydoca, który to potrafi.
Ma on niby swój markup dla docstringów, ale potrafi, przy pomocy
docutils obsłużyć także reStructuredText (ale tylko tworząc
dokumentację w HTML). Więc to właśnie podpiąłem pod doc/Makefile.
Okazało się, że stare kawałki dokumentacji musiałem popoprawiać, żeby
Epydoc sobie z tym poradził. Nowe tworzyłem od razu pod
tandem Epydoc+docutils. I nawet są jakieś
efekty. Otrzymana dokumentacja wygląda nieźle, jest dość przejrzysta… tylko
ma olbrzymie braki. :-( Kiedy ja to wszystko opiszę?

Powydawałem trochę…

Powydawałem trochę oprogramowania. Hurtem:
PyXMPP 0.5
CJC 0.5
JJIGW 0.2.
Jeszcze do napisania anonsy na główną stronę JabberStudio, ale
na razie mi się nie chce ich pisać. Pewnie zaraz się okaże, że
w każdym z tych programów jest jakiś krytyczny błąd, z jakim
nie powinno się wydawać. Trudno, kolejny rilis pewnie i tak za
jakieś dwa miesiące lub pół roku, bo wcześniej nie będzie mi
się chciało.

W PyXMPP i CJC główną nowością jest obsługa rozmów grupowych,
w JJIGW poprawa stabilności i obsługa wielu sieci IRC. We
wszystkich poprawiona masa błędów i wprowadzonych nieco nowych.

A w pracy dzisiaj robię za tragarza… :-(

JJ i CIA

Napisali o mojej twórczości w Jabber Journal, ale moja
wrodzona skromność nie pozwala mi się tym chwalić. Więc się nie pochwalę
:-P

Aby moja sława nie zanikła postanowiłem też zadbać o regularne donosy do
CIA. Niestety na JabberStudio nie mam dostępu
do /CVSROOT/ i nie mogę bezpośrednio instalować commit-skryptów.
Mam jednak możliwość skierowania informacji od commita na dowolny JID lub adres
e-mail i z tej właśnie możliwości skorzystałem. Musiałem tylko napisać skrypt
do konwersji wiadomości z JS na XML zrozumiały dla CIA – niecała godzinka
roboty. Od dziś więc notowane będą moje commity nie tylko do
PLD,
ale także do:
PyXMPP,
CJC,
JJIGW
i
Transportu GG.

Obfalkać drzwi…

Gdy wychodziliśmy z Krysią na spacerek kichnąłem. Tak porządnie i w kierunku
drzwi sąsiadów. Krysię bardzo to rozśmieszyło. Zażartowałem, że obsmarkałem
drzwi sąsiadów
. Śmiała się jeszcze bardziej, powtarzając obfalkał
drzwi
. Później jej przeszło.

Gdy wracaliśmy, piętro pod naszymi drzwiami Krysia pociągnęła mnie w kierunku
drzwi, mówiąc: obfalkać drzwi!, ja na to nie obsmarkam drzwi sąsiadom,
ona: dzidzia obfalka!. Podeszła do drzwi i dmuchnęła nosem. Była bardzo
z siebie zadowolona.

A za chwilkę zabieram się za optymalizacją PyXMPP. Teraz w CJC jak napisze
/chat ktos@ i nacisnę dwa razy TAB, to ponad minutę muszę czekać aż
dostanę dwa pasujące JIDy do wyboru. Tak raczej być nie może. Myślę, że cache
JID-ów i wyników stringprep pomoże. Wcześniej muszę jednak z JID-ów
zrobić obiekty immutable i nie wiem czy dużo nie będę musiał poprawiać
(API się zmieni odrobinkę).

Porządki w kodzie i na Joggerze

Wywaliłem z PyXMPP wsparcie dla Pythona 2.2 i spróbowałem użyć modułu
datetime do obsługi timestampów. Okazało się, że jednak nie
rozwiązuje on moich problemów. Zapewnia interfejs do zamiany czasu
pomiędzy lokalnym a UTC, ale… tylko wtedy jak mu się poda klasy
reprezentujące odpowiednie strefy czasowe. A Python w module
datetime udostępnia jedynie abstrakcyjną klasę bazową.
Resztę trzeba sobie napisać. UTC to nie problem, ale przecież nie będę
pisał klas opisujących strefy czasowe wszystkich potencjalnych
użytkowników CJC! Jest gdzieś w sieci moduł zawierający gotowe klasy,
ale ja nie chcę dodawać kolejnej zależności, szczególnie, że przecież
w systemie już jest informacja o strefie czasowej użytkownika.

Zajrzałem do dokumentacji glibc, żeby zobaczyć jak się to w C robi. Jest
tam nawet potrzebna mi funkcja, nazywa się timegm,
ale:

*Portability note:* `mktime’ is essentially universally
available. `timegm’ is rather rare. For the most portable
conversion from a UTC broken-down time to a simple time, set the
`TZ’ environment variable to UTC, call `mktime’, then set `TZ’
back.

Fajnie, że podali przenośny sposób, ale zastosowanie jego w aplikacji
wielowątkowej to byłaby zbrodnia. A więc sposobu praktycznie nie ma.
Jednak nie będę przecież użytkownikom pokazywał czasu UTC, więc zacząłem
kombinować i nawet coś wykombinowałem: zamiana czasu UTC na lokalny
medodą kolejnych przybliżeń. Z moich testów — z czasem letnim
i zimowym z różnymi ustawieniami zmiennej $TZ
wynika że to nawet działa :-). Ciekawe jak bardzo
przekombinowałem.

Dzisiaj, nie mając wiele do roboty w pracy, urządziłem bug fixing
day
dla CJC. Poprawiłem już dwa błędy zgłoszone na JS oraz
kilka zgłoszonych przez Jabbera. Poczekam jeszcze na jakieś bugreporty
i może zrobię kolejne wydanie PyXMPP i CJC. MUC jeszcze dość
niekompletny, ale używalny, a wydać warto chociażby z powodu błędów
poprawionych w stosunku do 0.4.

Oprócz porządków w kodzie zrobiłem też porządki na Joggerze. Uzupełniłem
polecane Jogi o nowe pozycje i atrybuty title na linkach.
Usunąłem też linki erotycznie, ale nie dlatego że nagle sporządniałem
— po prostu nie chciało mi się ich uaktualniać. Poprawiłem jeszcze
ostatnią notkę — zamieniłem na w kilku
miejscach. Od dziś postaram się trzymać zasad typografii. Z poprawianiem
starszych notek byłoby za dużo roboty.