CJC i PyXMPP 1.0.1

Ostatnie wydanie CJC i PyXMPP było ponad trzy lata temu – w grudniu 2005 roku. Po tamtym wydaniu zacząłem poważne zmiany w API… i nigdy ich nie skończyłem, a niedokończonego dzieła wydawać nie chciałem. Potem przyszły kłopoty ze zdrowiem, pośrednio wynikłe też z mojego zaangażowania w Open Source (czyt. siedzenia całymi dniami przed kompem, świata nie widząc) i postanowiłem unikać angażowania się w kodowanie. Tak więc, planowane zmiany nigdy nie miały być dokończone.

W międzyczasie jednak w starym kodzie znajdowane były błędy, od czasu do czasu jakiś błąd poprawiłem, czasem ktoś podesłał patcha, to wrzucałem do SVN. Pojawiały się nowe wersje Pythona, czy M2Crypto, to kod dostosowywałem odpowiednio (CJC używam na co dzień, moja żona też, więc to musi działać). Właściwie, jak ktoś jeszcze używał PyXMPP albo CJC, to któryś z ostatnich snapshotów.

Ostatnio zastanawiałem się też, czy nie spróbować do CJC wreszcie dodać obsługi UTF-8. Wcześniej tego odmawiałem, bo Pythonowy moduł curses w ogóle nie ma obsługi Unicode, tylko start 8-bitowe API. I nic nie wskazuje na to, że to ktoś poprawi, ale uż jakiś czas temu jeden z użytkowników udowadniał mi, że to się jednak da zrobić, jeśli tylko moduł curses jest zlinkowany z biblioteką „libncursesw”. W PLD długo tak nie było, ale w Th już jest. To czemu by nie spróbować?

Wczoraj więc spróbowałem. Wyświetlanie UTF-8 działało bez żadnych zmian w kodzie, ale żeby wczytywać znaki Unicode z klawiatury musiałem dodać brzydkiego hacka. I w ogóle trochę obsługi klawiatury przerobić. Udało się. A skoro wreszcie się pojawiła funkcjonalność tak wyczekiwana przez użytkowników, to czemu by nie wydać nowej wersji? Resztę dnia spędziłem
przygotowując paczki z PyXMPP 1.0.1 (w tym jeszcze przed wydaniem poprawiłem jednego paskudnego babola) i CJC 1.0.1. Dzisiaj wysłałem informacje o wydaniach na listy mailowe dotyczące tych produktów. No to chyba udało mi się coś wydać. :-)

Po następne wersje zapraszam za trzy lata. ;-)

Committed revision 666.

Mam dosyć sztywnego trzymania się niektórych zasad dobrego stylu
programowania. Pisząc CJC starałem się
w ogóle nie używać zmiennych globalnych, bo przecież każdy wie, że tak trzeba.
No i dało się, jednak z tak zrobionego kodu nie byłem zadowolony. Mam tam
takie trzy obiekty, właściwie singletony, do których dostęp potrzebny był
w bardzo wielu miejscach. No i dostęp ten odbywał się właściwie na dwa
sposoby: albo referencja do takiego obiektu była przekazywana w konstruktorze i potem
zapisywana w atrybucie obiektu który tego potrzebował, albo dostęp odbywał się
przez inne obiekty (np.: self.plugin.app.screen) –
jedno i drugie nie wyglądały najlepiej. Standardowym, Javowe,
rozwiązanie, w postaci statycznej metody zwracającej instancję singletona,
niespecjalnie mi pasowało – to takie niepythonowe odwoływać się do
klasy, gdy tylko jej instancja jest potrzebna. Do tego to więcej pisania by
było, a przecież miałem API uprościć.

W końcu zdecydowałem się na rozwiązanie proste i skuteczne –
zrobiłem moduł cjc_globals z trzema zmiennymi globalnymi. I wszystko
byłoby dobrze, gdyby nie komunikat przy commicie, wyraźnie sugerujący, że
za moją decyzją stoi Zło: Committed revision 666.
;-)

Okularków nie będzie, przenosiny w pełni

Dzisiaj wybrałem się do okulisty (przy optyku) w celu dobrania okularów.
Ten mnie zbadał, próbował dobrać odpowiednie szkła… i właściwie nic to nie
dawało. Na siłę okularów sprawiał sobie nie będę – to by mi mogło
bardziej zaszkodzić niż pomóc. To co zaobserwowałem u okulistki podczas badań
kontrolnych najprawdopodobniej było tylko złudzeniem spowodowanym
powiększającym działaniem szkieł. Dzisiaj więc zamiast recepty na okulary
odebrałem receptę na krople do oczu. Zresztą podobne to tych co już mam –
do Starazolinu, który wychwalałem już w zeszłym roku.

W związku ze zmianą pracy (do nowej już w czwartek) przenoszę różne
rzeczy. Listy dyskusyjne moich projektów (CJC, PyXMPP, Transport GG)
przeniosłem na swój własny serwerek (lists.jajcus.net), a z rozpędu zabrałem
się za przenoszenie do siebie reszty tych projektów z JabberStudio (które najwyraźniej
umiera). To ostatnie jeszcze trochę potrwa, bo to większa robota, ale pewnie
w tym tygodniu skończę – wtedy dam znać co i jak, a przede wszystkim,
gdzie.

Dzisiaj walczyłem jeszcze z dwie godziny z przenoszeniem kontaktów ze
starego telefonu komórkowego (firmowego) na mój własny, prywatny. Ta marna
namiastka IrDA/OBEX w moim Samsungu nie ułatwiała sprawy, ale stary laptop
z IRDA, Multisync, trochę Pythona, trochę ręcznego grzebania w plikach
wizytówek (bez tego, przy próbie importu czterech z moich kontaktów telefon
się po prostu rebootował) i jakoś się udało. BTW: jak ktoś ma mój stary numer,
a chciałby aktualny, to niech się do mnie zgłosi.

Z przenosin czeka mnie jeszcze wyniesienie swoich fizycznych zabawek (talerz,
słuchawki, puszka na herbatę, kalendarz z gołymi babami itp.) ze starej roboty
i zaniesienie sprzętu (komputer, monitor, telefony) do nowej. Z mniej
materialnych rzeczy – posprzątanie po sobie na serwerach w starej firmie
(wszelkie konta, aliasy, skrypty itp. zabawki) i podczepienie się do nowej
(też se będę musiał jakiegoś majla założyć). System niby sobie już na nowym
kompie zainstalowałem, ale nie pamiętam w jakim jest stanie… więc może
jeszcze to mi trochę czasu zająć… a pracodawca pewnie będzie chciał już
pierwszego dnia widzieć wyniki… ;-)

Migracja

Wynoszę się z firmy, w której stoi mój dotychczasowy serwer Jabbera. Chcąc
się od niej całkiem uniezależnić zmuszony byłem zmienić i JIDa. Od kilku dni więc
szykowałem swój nowy serwerek, a od wczoraj zacząłem uzupełniać CJC o funkcje ułatwiające migrację.

Nowe ficzery to polecenia:

/export_roster
Eksportuje roster do pliku XML.
/import_roster
Importuje roster z pliku XML – dodaje do rostera wpisy z pliku,
których w rosterze jeszcze nie było i wysyła prośby o subskrypcję dla wpisów
które w pliku mają subskrypcję to lub both.
/multi_message
Wysyła wiadomość jednocześnie do wielu użytkowników z rostera,
wybranych filtrem podobnym do tego używanego przez /list

Dzisiaj wypróbowałem nowe funkcje w warunkach bojowych. Wyeksportowałem
roster na starym koncie, wysłałem wiadomość o zmianie JIDa do wszystkich
kontaktów z subskrypcją from lub both i zaimportowałem roster na
nowym koncie. W ciągu pierwszej minuty od tej operacji dostałem około 50 próśb
o autoryzację – nigdy wcześniej nie widziałem tylu otwartych
zakładek w CJC %-).

W samą migrację nie chciałem mieszać transportów i botów, więc wcześniej
zrobiłem z tym porządki – wywaliłem transport ICQ, przeniosłem ręcznie
te kilka kontaktów na GG, zmieniłem JIDa w Joggerze. Tylko jeden bot się
odezwał na to moje /multi_message, ale chyba nic nie
narozrabiałem. W ogóle cała ta migracja przeszła coś naspodziewanie gładko…
zobaczymy co będzie dalej.

Jak jeszcze będzie mi się chciało, to zrobię sobie jeszcze małego bocika,
który będzie zalogowany na stare konto i będzie mi forwardował wiadomości na
nowe. Jak nie, to będę co jakiś czas logował się ręcznie i patrzył co się tam
dzieje. Dorobienie obsługi wielu kont do CJC, to byłoby stanowczo za dużo
roboty.

Nowy Jogger – nowy szablon

Zmienił się engine Joggera, czas na zmiany na własnym Joggerze. Już sam
miałem trochę dosyć tego ciemnoniebieskiego czegoś. A, że bardzo mi się podoba
domyślna skórka Zope3 – rotterdam, to sobie ją pożyczyłem.

Dodałem tylko prosty, dwukolumnowy layout, powiększyłem <h1/>
i zamieniłem wszelkie microsoftowe czcionki na bardziej wolne zamienniki.
Postawiłem też na prostotę – wywaliłem z szablonu wszystko co zbędne
(chociaż parę rzeczy jeszcze pewnie wróci). Mnie się efekt podoba. Żonie też.
Chyba więc nie jest źle. :-)

P.S. przy okazji sprawdzam, czy plugin jogger w CJC działa
z Jogger 2…

Update: usunąłem ze stylu konkretne nazwy fontów, każdy będzie widział to co ma w przeglądarce/systemie skonfigurowane.

Ufff… CJC 1.0.0 i PyXMPP 1.0.0 już są.

Ufff… wydałem CJC 1.0.0 i PyXMPP 1.0.0. Nie znoszę wydawać
nowych wersji! Nie dość, że wypada najpierw wszystko doprowadzić do porządku,
to jeszcze trzeba się wysilić na jakieś announcement do JabberStudio
itp. A jeszcze JabberStudio jest spieprzone i np. nie przyjmuje wersji
1.0.0, więc nowe pliki oznaczone są jako wersja 0.1.
pyxmpp-1.0.0.tar.gz jest w serwisie umieszczony dwa razy —
myślałem, że się po prostu pomyliłem i jak go wpiszę od nowa (edycja
poprzedniego wpisu nie pomagała), to zadziała. Nie zadziałało, a już wydanego
pliku skasować nie można… super. I jeszcze mnie czeka jakieś ogłoszenie na
listy… wrrr… Wręcz się kodować odechciewa.

Numer wersji 1.0.0 nie oznacza wcale, że to nagle jakieś super stabilne
oprogramowanie. Po prostu uznałem, że nie będę latami ciągnął numeracji
ułamkowej. Poprzednie wersje (0.5) zostały wydane ponad rok temu, mają
straszne braki i nie działają z nowym Pythonem i libxml2. Ale ludzi wciąż to
ściągali, bo nowszego oficjalnego wydania nie było. No to już jest.
Pewnie od jutra (dzisiaj nie, bo dzisiaj miałbym jeszcze czas coś poprawić)
sypną się bugreporty… pewnie pełno jest paskudnych błędów, które tylko
u mnie jakimś trafem się nie objawiły. Poprawi się w wersji 1.0.1… tylko
kiedy będę miał czas ją wydać? Na Wielkanoc? ;-)

Ech… coś niezbyt optymistycznie mi to ogłoszenie wyszło…

Google Talk

[08:04] Resolving 'talk.google.com'...
[08:04] Connecting to 216.239.37.125:5222...
[08:04] Connected to 216.239.37.125:5222.
[08:04] Doing TLS handshake with gmail.com.
[08:04] Encrypted connection to gmail.com established using cipher EDH-RSA-DES-CBC3-SHA.
[08:04] Binding to resource CJC...
[08:04] Authorized as jajcus@gmail.com/CJCE5DFD7C2.
[08:04] Got roster
[08:06] Peer certificate saved to: /home/users/jacek/.cjc/known_certs/talk.google.com.der

Wczoraj wieczorem jeszcze nie wpuszczał, a nawet hackowałem CJC myśląc, że
to różnice w implementacji protokołu. Ale widać jak mieli dzisiaj odpalić, to
odpalili dzisiaj. Połączyło się bez żadnego hackowania. Niestety, komunikacja
z innymi serwerami nie działa. Mam nadzieję, że to przejściowe.

W każdym razie Jabberowy serwer Google działa i to najwyraźniej w miarę
zgodnie z XMPP 1.0 (StartTLS, SASL).

Rzucam to wszystko…

Zastanowiłem się nad tym co napisał zgoda w komentarzach do
ostatniego wpisu
i chyba muszę się z tym zgodzić. Ci wielcy gracze
to nic dobrego, zaraz wszystko zepsują. Teraz Sun zaczyna — psując
wspaniałą ideę tekstowej komunikacji przez jakieś VoIP, videokonferencje itp.
wynalazki w swojej implementacji. Potem będzie Microsoft, skoro jest RFC, to
będą musieli zrobić swoją implementację. W każdym Windows będzie klient
Jabbera, którego nawet moja matka obsłuży. Zdaje się, że Apple już coś takiego
zrobiło (na szczęście u nas Maki nie są zbyt popularne). No i po co to nam? Nie
po to robię trudnego do zainstalowania, brzydkiego klienta CJC, żeby gadać
z ludźmi, co u siebie mają śliczne cukierkowe okienka i, co gorsza, cieszą się
z narzędzia, którego używają! Nie po to robiłem transport GG, żeby przestał
być potrzebny jak ludzie z GG uciekną.

Ostatecznie stwierdzam, że dam sobie z tym spokój. Dość ślęczenia nad
PyXMPP i CJC, wystarczająco czasu na to zmarnowałem. Transport GG też okazał się niewypałem,
zamiast pozwalać ludziom z GG gadać z Jabberowcami, jak już muszą, to
spowodował przejście iluś użytkowników GG na Jabbera — straszne. Tego bloga też zamykam,
przeniosę się gdzieś, gdzie nie ma takich niepotrzebnych bajerów jak dodawanie
notek z jakiegoś komunikatora, czy powiadomienia, co rozpraszają człowieka przy normalnej pracy.

Więcej o tym, czemu XMPP ssie i czemu nie chcę mieć z tym już nic wspólnego
opowiem na Pingwinariach, zamiast wykładu o tym głupim publish-subscribe
— myślę że ludzie będą mi za to wdzięczni.

Różności…

Ten wpis napisałem wczoraj, ale że Jogger nie działał, to idzie teraz…

Mozilla Team mnie zaskoczyło. Gdy mi po upgrade się Firefox wywalał przy
wpisaniu czegokolwiek w pasku adresu, to użyłem Quality Feedback Agent do
wysłania raportu. Bez jakichkolwiek nadziei, że coś z tego wyniknie. A
jednak. Dostałem odpowiedź, z automatu, że problem został wyjaśniony,
instrukcję jak sobie z nim poradzić (sam sobie poradziłem wcześniej) i radę na
przyszłość. Czyli to jednak działa :-).

A ostatnio znowu trochę dłubię przy CJC i PyXMPP. Repozytoria SVN na
JabberStudio już mi działają, więc mogę commitować co zrobię i jest jakaś
motywacja. Kommitnąłem poprawki które się nazbierały w czasie gdy JabberStudio
nie działało i poprawiłem jakieś drobne błędy w CJC, które zresztą znałem już od
dawna i od dawna wiedziałem jak je poprawić. A w PyXMPP zrobiłem Pythonowe
wersje klas i funkcji z kompilowanego modułu _xmlextra. Są to
obrzydliwe hacki, dużo wolniejsze od oryginałów, ale przynajmniej można teraz
PyXMPP używać bez żadnego kompilowania (zakładając, że się ma moduły libxml2
już skompilowane), co powinno ułatwić coniektórym instalację. Przy okazji
powkurzałem się na libxml2 który potrafi generować bzdurny kod
XML po zmianie przestrzeni nazw elementu w drzewie dokumentu. Zgłosiłem to na
listę dyskusyjną, może też zgłoszę do bugzilli. Jakoś ten problem nie wpłynął
na działanie CJC (przypadek), więc na razie go olewam. Muszę jeszcze odpalić
ponownie automatykę do snapshotów, żeby ludzie mogli moją aktualną twórczość
ściągać.

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
;-).