Od jakiegoś czasu wymyślam sobie różne udoskonalenia dla Vima, i piszę je zazwyczaj w Pythonie :) Niedawno opisywałem jak wyświetlić listę funkcji z edytowanego pliku, później zrobiłem sobie wygodne komentowanie kodu (wersje które znalazłem na sieci nie satysfakcjonowały mnie), teraz przyszedł czas na sprytne (w sensie: wygodne) uruchamianie właśnie edytowanego skryptu/programu :)

Do niedawna używałem prostego Pythonowego skryptu, który wywoływem z Vima:

!$ %

Wykrzyknik to polecenie wywołania programu z shella, $ to nazwa skryptu, a % jest rozwijany przez Vima do pełnej ścieżki bieżącego pliku. Było to o tyle wygodne, że nieważne w jakim języku pisałny był skrypt/program, $ uruchamiał odpowiedni interpreter, ze skonfigurowanymi parametrami i wyświetlał wyjście. Tą funkcjonalność oczywiście potrzebowałem zachować, ale wykonywanie zewnętrznego programu jest strasznie niewygodne ;) Więc zrobiłem sobie wygodniejszą, i nieco bardziej rozbudowaną wersję. Inne założenia to możliwość przekazywania parametrów do wykonywanego programu, oraz dla niektórych języków możliwość wcześniejszej, automatycznej kompilacji.

Przejdź do reszty tego wpisu »


Jakiś czas temu napisałem artykuł o setterach i getterach w PHP5. Może warto poruszyć podobny temat dotyczący Pythona? :)

Przede wszystkim, model obiektowy Pythona jest zupełnie inny niż PHP. Nie będę go tu omawiał, ponieważ to temat na dość obszerną książkę :) Generalnie obiektówka Pythona jest pełniejsza, ma większe możliwości przeciążania zarówno metod, jak i operatorów (których w PHP przeciążyć nie można).

Przejdź do reszty tego wpisu »


Już od jakiegoś czasu deweloperzy Pythona przygotowują nową, niekompatybilną z poprzednimi, wersję Pythona. Python, gdyby ktoś nie wiedział, to jeden z najfajniejszych języków jakie wymyślono ;) (oczywiście to mocno subiektywne uczucie, ale może kogoś zachęci ;) ). Napiszę tutaj o dwóch ważnych zmianach, co do których nie byłem zupełnie przekonany (a konkretnie: w ogóle nie byłem przekonany), a które spodobały mi się po dzisiejszej krótkiej zabawie z wersją alpha3 Pythona 3000 :)

Przejdź do reszty tego wpisu »


Stwierdziłem niedawno, że brakuje mi w Vimie takiego drobiazgu jak wyświetlanie listy funkcji z edytowanego właśnie pliku. Można z jednej strony wykorzystać ctags, ale (pewien nie jestem, nie jestem znawcą tagsów ani ich obsługi w Vimie) po dodaniu funkcji/metody/czegokolwiek innego co można by nazwać tagiem trzeba by od nowa generować listę tagów. Nie jest to problemem takim bardzo dużym, do momentu gdy ciągle pracuje się nad różnymi projektami, z czego sporej części nie mam na dysku (tylko wykorzystując plugin netrw pracuję via ftp). W tym momencie moja znajomość systemu ctags podpowiada mi że robi się ciężko…

Postanowiłem więc napisać sobie prosty skrypt do tego, a że język wewnętrzny Vima mnie nieco odrzuca, postawiłem na Pythona ;) Żeby jakikolwiek skrypt pythona (jak ktoś lubi, można użyć też np perla) mógł zadziałać w Vimie, ten ostatni musi być skompilowany z jego obsługą. W Ubuntu wystarczy zainstalować pakiet vim-full. Łatwo sprawdzić czy Vim ma wkompilowaną obsługę pythona:

Przejdź do reszty tego wpisu »


Jako, że zbliża się koniec ważności mojego konta na DreamHost, a przedłużać go zamiaru nawet namniejszego nie mam, zaczęłem się przygotowywać do migracji. Jeszcze nie wiem gdzie pójdę sobie, ale pójdę na pewno :)

Jedną z rzeczy z tym związanych jest usunięcie mojego repo (repo.urzenia.net). Cała jego zawartość znajdzie się niedługo jako konkretne projekty na code.google.com. W sumie już wszystko przeniosłem, poza BlipApi.php, które też się tam niedługo znajdzie. Nowe adresy projektów to:

mPack
zestaw bibliotek pomocnych przy tworzeniu serwisów w PHP: m-pack.googlecode.com.
useless-scripts
kilka skryptów które wykorzystuje w mojej codziennej pracy na komputerze: useless-scripts.googlecode.com. Tutaj też dostał się mój ostatni “produkt” killer.pl.
WP Blip!
Plugin do WordPressa, wyświetlający na nim ostatnie wpisy z serwisu Blip!: wp-blip.googlecode.com.

Przed chwilą dokonałem jednej korekty w skrypcie: jako że czasem nie mogę się połączyć i pobrać blacklisty, stworzyłem możliwość 5-okrotnej (domyślnie - ustala to zmienna TRIES) próby pobrania blacklisty SBLAM!. Dopiero po pięciu próbach skrypt zakończy działalność. Każda kolejna próba jest opóźniona o domyślnie 5 (zmienna DELAY) sekund, przy czym każda kolejna próba dodaje do wartości samą siebie, czyli po drugim niepowodzeniu DELAY ustawi się na wartość 2*DELAY. Przykład:

  • pierwsza próba - z marszu
  • druga próba - po pięciu sekundach
  • trzecia próba - po dziesięciu sekundach
  • czwarta próba - po dwudziestu sekundach
  • piąta próba - po czterdziestu sekundach

Dodatkowym “fiuczerem” jest wywalenie stamtąd wszystkich polskich znaków - coś mi się wysypywał skrypt przez nie, a nie mam teraz czasu na debugowanie dlaczego.

Skrypt do pobrania z adresu: urzenia.net/wp-content/sblam_blacklist_update.txt.


porneL jakiś czas temu zaczął publikować czarną listę spamerów. Uznałem to za świetny pomysł z jego strony, wart wykorzystania. Chwilę później napisałem skrypcik, który pobiera aktualną blacklistę, i dodaje ją do pliku .htaccess na serwerze, blokującym odwiedzającym z tego adresu IP na dostanie się do naszej witryny. Oczywiście mowa tylko o spamerach :)

Skrypt jest bardzo prosty - pobiera blacklistę, dopisuje ją do .htaccess, robiąc wcześniej kopię zapasową, i kończy pracę. Równie prosta jest jego konfiguracja wewnątrz:

HTACCESS
wskazuje na plik .htaccess który będziemy uaktualniać. W przykładowym skrypcie jest ona generowana, jednak nie widzę przeszkód aby wpisać ją na sztywno, np: HTACCESS = '/home/user/public_html/.htaccess'.
BKPDIR
Katalog w którym zostanie utworzona kopia zapasowa .htaccess. Jeśli puste, przyjmuje że kopia zapasowa będzie tworzona w katalogu macierzystym obecnego .htaccess.
BLACKLIST
url do pliku z blacklistą
DEBUG
Jeśli przyjmie wartość prawdy logicznej (np, True, 1) to na stderr będzie wypisywać komunikaty z pracy skryptu.

Skrypt (jego już druga wersja) jest na licencji GPL v.2. Ja nie biorę odczywiście odpowiedzialności za jego nieprawidłowe działanie :) Ale wszelkie błędy i raporty można zgłaszać do mnie, a ja będę starał się je poprawiać :) Do pobrania stąd: urzenia.net/wp-content/sblam_blacklist_update.txt (warto zmienić rozszerzenie pliku na .py).

Jeszcze słówko o najlepszym użyciu:

Ja osobiście wstawiłem sobie do crona linijkę:

12 6 * * * /home/mysz/bin/sblam_blacklist_update.py

Dzięki czemu o godzinie 6.12 każdego dnia mam uaktualnianą blacklistę spamerów :)


Próbka kodu, z jakim się zmagałem przez dłuższy czas:

[mysz@urzenia ~/p/python/mtalog]% python2.5
Python 2.5.1 (r251:54863, May  2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> db = sqlite3.connect(':memory:')
>>> cur = db.cursor()
>>> cur.execute('BEGIN')
<sqlite3.Cursor object at 0x40201f80>
>>> cur.execute('CREATE TABLE `test` (`id` INTEGER PRIMARY KEY, data TEXT)')
<sqlite3.Cursor object at 0x40201f80>
>>> cur.execute('COMMIT')
<sqlite3.Cursor object at 0x40201f80>
>>> cur.execute('BEGIN')
<sqlite3.Cursor object at 0x40201f80>
>>> cur.execute('INSERT INTO `test` (`data`) VALUES ("asd")')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: SQL logic error or missing database
>>> 

Co bym nie zrobił, wysypywało się albo z powyższym wiele mówiącym błędem, albo też chodziło czysto, a po zakmnięciu połączenia (oczywiście nie mówię tutaj o bazie testowej założonej w ramie, jak w przykładzie) baza była pusta. Nawalczyłem się z tym nieco… a rozwiązanie, jak to w życiu, jest banalne.

pysqlite działa natywnie w takim pseudo-trybie autocommita. Nieco próba automatyzacji. Generalnie polega to mniej więcej na tym, że sam zaczyna transakcję jeśli trafi na polecenie INSERT/UPDATE/DELETE/REPLACE, ale w sumie nie doczytałem kiedy ją kończy. Mało mnie to interesuje, bo ja chcę ręcznie zaczynać i kończyć transakcje, a automatyzacja w/w zawiodła (jak pisałem: po zakończeniu połączenia danych w bazie niet :/ ).

Aby kontrolować tryb w jakim pysqlite rozpoczyna i kończy transakcje, potrzeba zmienić wartość właściwości isolation_level naszego połączenia z bazą. W moim przypadku najbardziej pasująca wartość to None, w związku z czym nawiązanie połączenia z bazą będzie wyglądało w ten sposób:

[...]
        self.db.connect ( '/path/to/db.sqlite3' )
        self.db.isolation_level = None
[...]

Od tego momentu sqlite czyna tańczyć jak mu każemy, czyli możemy ręcznie rozpoczynać transakcję, wybierać jej rodzaj, kończyć transakcję czy też ją ROLLBACKnąć etc. W końcu…

A niniejszy wpis dedykuję wszystkim którzy podobnie jak ja walczyli przez kilka/kilkanaście godzin nad taką głupotą :/


Strona 1 z 4