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ą :/


Jakiś czas temu, gdy spam w akismecie przekroczył barierę krytyczną (na tą chwilę mam odfiltrowane poprzez Akismet ponad 30k sztuk spamu), zrobiłem sobie mały, prosty skrypt który odwiedza mi stronę w adminie WordPressa, zbiera odfiltrowane IP postów, i zapisuje mi je, odfiltrowując klasy adresowe z Polski. Skrypcik nazwałem asipht. Dzięki niemu mam mniej więcej podgląd na to, z jakiego IP najczęściej spam dostaję, i najbardziej wybitne persony dodaję bezwarunkowo do .htaccess, w którym mam też kilka klas adresowych zerżniętych chamsko od Mikołaja :)

Skrypt nie jest doskonały, powiedziałbym wręcz że dużo mu brakuje, ale nie chce mi się dodawać więcej funkcjonalności, starcza mi to co jest. Najbardziej przydałaby się opcja porządnego logowania do serwisu, ale w zamian tego podałem mu cookiesy uwierzytelniające z WP :)

Jak ja tego używam: raz dziennie sprawdzam sobie w akismet czy coś się nie zaplątało, jeśli nie to odpalam asipht, a następnie usuwam wszystkie spamowe komentarze (circa 200 dziennie, choć zdarzało się i 1.5k). Za pomoca drugiego skryptu, asiphtstats, podglądam jakie adresy IP “wygrywają” w konkurencji najwięcej spamu z jednego adresu IP, a później ręcznie dodaję sobie zwycięzców do .htaccess, zapewniając sobie tym święty spokój od tego pismaka :)

Gdyby ktoś był zainteresowany takim skrypcikiem, to używane przeze mnie pliki można sobie pobrać z adresu urzenia.net/wp-content/asipht/.

Acha, odnośnie konfiguracji (znajdującej się pod koniec pliku asipht):

c_user_n
nazwa cookie z nazwą użytkownika (coś w stylu: wordpressuser_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
c_user_v
zawartość tegoż cookie
c_pass_n
nazwa cookie z hasłem (np. ‘wordpresspass_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’)
c_pass_v
zawartość tegoż cookie
c_domain
nazwa domeny dla jakiej przeznaczone jest cookie
c_path
ścieżka dla cookie
url
pełen URL do strony z Akismet w naszym WP
savepath
określa ścieżkę zapisu pliku z zebranymi spamerskimi IP
whitelist
ścieżka do pliku z zakresami IP które nie będą dodawane do bazy, np: 217.119.64.0 217.119.79.255
pages
boolean, określa czy nasz Akismet stronicuje wyniki zebranego spamu (tak jak w nowej wersji), czy też nie (jak w starszej, lub zmodyfikowanej mojej :) )

Wcześniej zrobiłem błąd, że próbowałem wstawić tenże tutorial jako osobną stronę, nie powiązaną z diary. Później, po przenosinach diary na inny serwer, zupełnie o tym zapomniałem, i trzy tłumaczenia tutoriala Django niespecjalnie działały…

Niniejszym naprawiam tenże błąd, i umieszczam je tam gdzie zawsze powinny być już dostępne:

Na razie więcej części nie ma, zająłem się innymi rzeczami, i zapomniałem o przetłumaczeniu ostatniej, czwartej części tutoriala. Postaram się to nadrobić za jakieś 2 tygodnie, jak wrócę do więzienia…

Przeniosłem też kilka działów (vimtips, humor) do kategorii ‘wszystkie’, zostawiając, tak jakby poza głównym nurtem, świeże kategorie: urzenia.net gdzie są informacje odnośnie samego diary, i Artykuły, gdzie będą umiesczane tłumaczenia i artykuły różnej maści.


Przejdź do reszty tego wpisu »


Przejdź do reszty tego wpisu »


Przejdź do reszty tego wpisu »


W ramach treningu o zabawy, w wyniku pewnego zapytania napisałem takie coś - może się komuś przyda. Jako parametr należy podać nazwy plików html w których należy uzupełnić tagi <img /> o wymiary obrazków.

#!/usr/bin/env python
# -*- coding: iso-8859-2 -*-
import os.path
import re
import Image
import sys

if len(sys.argv) == 1:
  print 'Podaj nazwy plików'

def replace(html):
  rx = r'''(?im)(<\\s*img\\s*src=(["'])(?P.*?)\\2.*?/>)'''
  imgs = re.findall(rx, html) #, re.I|re.M)
  if imgs:
    for imgtag, tmp, fname in imgs:
      if imgtag.find('width=') == -1 and\\
          imgtag.find('height=') == -1 and\\
          os.path.isfile(fname):
        intag = 'width="%dpx" height="%dpx"' % Image.open(fname).size
        ntag = imgtag[:-2] + intag + ' />'
        html = html.replace(imgtag, ntag)
  return html

files = sys.argv[1:]
for f in files:
  if not os.path.isfile(f):
    print 'Nie znaleziono:', f
    continue
  html = replace(open(f).read())
  open(f, 'w').write(html)

Wymagany jest moduł PIL.

Oczywiście jest to mocno niedopracowane, ale napisanie tego to było dosłownie kilka minut, dla zabawy, a jako że to jest python, to łatwo samemu to dopracować i poprawić :) Ważne, że działa jak powinno…


Kolejny mały urywek kodu, ten dotyczy wykrywania roku przestępnego.

Python:

def isleapyear(year):
  return (not year%4 and year%100 or not year%400)

PHP:

function is_leapYear($year)
{
  return (!($year%4) && ($year%100) || !($year%400));
}

C++:

bool isleapyear(int year)
{
  return (!(year%4) && (year%100) || !(year%400));
}