Гей-парад в Сан-Франциско, 2009

6/29/2009

Выложил фотографии гей-парада, который проходил в минувшее воскресенье в Сан-Франциско. Ниже фликровское слайд-шоу (нужен флеш), а вот прямая ссылка на фотографии.

Там же был махонькая демонстрация пуританских гомофобов против геев, лесбиянок и прочей угрозы национальной безопасности США (я серьезно, на одном плакате так и написано). Прямая ссылка на фотографии, слайдшоу ниже:

Гэвин Ньюсом

6/28/2009

Сегодня, SF Pride '09, мэр Сан-Франциско Гэвин Ньюсом.

Gavin Newsom on SF Pride '09

Новости нашего городка

6/24/2009

(06-24) 13:20 PDT ЮЖНОЕ САН-ФРАНЦИСКО — Бездомный врезал скейтбоурдом по лицу другого бездомного в результате спора на тему квантовой физики и расщепления атомов. SFGate

Ошибка в несуществующем файле

6/15/2009

Интересное случилось на работе. Началось всё с того, что некоторые тесты при своем падении начали тащить за собой весь фреймворк. Т. е. выполняется тест, в тестируемом файле вылезает какая-нибудь ошибка и, вместо того, чтобы записать её в лог и красиво закончить работу, вся тестинговая подсистема падает с сообщением AttributeError: 'NoneType' object has no attribute 'startswith'. Это проявлялось только у меня на компьютере, поэтому, вооружившись дебаггером, я начал ковырять один такой тест.

Сразу выяснилось, что traceback.extract_tb иногда возвращал None вместо содержимого строки, на котором произошла ошибка. Далее джанга пыталась безуспешно вызвать метод startswith у None в результате чего и падала .

Функция extract_tb возвращает None вместо содержимого строки только тогда, когда исходный текст модуля не доступен. Я начал дебаггить модули traceback и linecache, чтобы понять почему мы не можем прочитать прекрасно читаемый файл и обнаружил чудесное:

(Pdb) tb.tb_frame.f_code
<code object click at 0x10894e8, \
file "/home/anton/disqus/disqus/contrib/selenium.py", line 268>

Дело в том, что у меня ни то, что этого файла, у меня даже /home на компьютере нет (на OS X пользовательские директории находятся в /Users). Т. е. в какой-то момент исключение генерировалось из несуществующего файла (cправедливости ради, стоит отметить, что правильная мысль о причине AttributeError у меня была ещё в самом начале, но я её почему-то отбросил). Увидев это, я понял отчего несуществующие файлы у меня бросаются исключениями. Осталось только провести небольшой эксперимент: найти правильный selenium.py, изменить дату модификации и запустить тест заново.

Всё дело в том, что я какое-то время пользовался этой же инсталляцией с удаленной линукс машины, монтировав директорию через sshfs. Линуксовый питон создавал .pyc файлы а, поскольку файл с того момента не менялся, мой текущий питон файлы не пересобирал и соответственно модуль selenium думал, что он находится по старому адресу и этот адрес отдавал дальше по запросу. Модуль traceback, получив такой адрес, пытался прочитать исходный текст файла, не находил его и возвращал None.

Разные вещи

6/10/2009

Музей компьтерной истории

Скопировал с фотоаппарата и выложил в сеть фотографии, которые я сделал в музее компьютерной истории, что в Маунтин-Вью.

MongoDB

Сегодня был в компании Slide на докладе о MongoDB. MongoDB это высоко-производительная, документо-ориентированная система без формальной схемы базы данных (если я правильно перевел high-performance, document-oriented schema-free database). Половину доклада можно было, в принципе, прочитать у них на сайте, а вот вторая половина — про автоматический шардинг — получилась весьма интересной.

Мы, на работе, тоже используем Монго, но пока только для нескольких небольших проектов. К примеру, все данные для нашего шортера адресов хранятся именно в этой базе данных.

Кстати, интересный факт: поскольку шелл для этой базы данных написан с использованием джаваскрипта, они используют джаваскрипт-интерпретатор. Так вот, раньше они пользовались V8, но недавно переключились на SpiderMonkey. Сегодня я спросил у авторов о причине и оказалось, что V8 очень трудно портировать на 64 битные системы. Вот и весь интересный факт.

Сан-Франциско

В Сан-Франциско холодно и нет солнца и это не смотря на то, что сейчас лето. Последние два-три дня вообще постоянные тучи и туманы.

Google I/O

Нашел себя среди официальных фотографий с Google I/O.

Сергей Брин на Google I/O

5/28/2009

Минут 10 назад, Сергей Брин дает интервью на Google I/O:

Sergey Brin

Пуританская страна

5/26/2009

Около часа назад, демонстрация возле Верховного Суда Калифорнии.

IMG_1379

Суд оставил Prop 8 в силе, тем самым оставив браки между геями вне закона.

UPD: Остальные фотографии.

Битовые поля

5/24/2009

Когда таблица в классической, реляционной базе данных достигает определенного размера процесс какого-либо изменения её структуры становится очень болезненным. Однако, по мере того, как ваша программа развивается и обрастает новым функционалом, добавлять дополнительную информацию просто необходимо.

У нас чаще всего к большим таблицам нужно добавлять поля-флаги: разрешены ли комментарии в треде, подтвердил ли пользователь свой эл. адрес и так далее. К примеру, с тем пор как мы запустили «социальные комментарии» (на русском это название звучит ещё хуже, чем на английском) к нашим источникам добавились ещё два сайта: Reddit и News YC. А это два новых флага в таблице.

Решение этой задачки далеко не ново и было взято моим коллегой Эндрю из Си: чтобы компактно хранить данные булевого типа в одном поле можно использовать битовые поля. С такими полями нет необходимости каждый раз менять структуру таблиц, достаточно лишь закрепить в коде следующий свободный бит за соответствующим флагом.

Ниже я написал небольшой пример, основанный на используемом нами подходе:

from functools import partial

def bitfield_handler(field, bit):
    mask = 2**bit

    def _bit_handler(self, value=None):
        if value is not None:
            oldvalue = (getattr(self, field, 0) or 0)
            if value:
                setattr(self, field, oldvalue | mask)
            else:
                setattr(self, field, oldvalue & (~mask))
        curvalue = (getattr(self, field, 0) or 0)
        return curvalue & mask

    return _bit_handler

properties_handler = partial(bitfield_handler, 'properties')

class User(object):
    def __init__(self):
        self.properties = 0

    IS_VERIFIED = properties_handler(0)
    RECEIVE_NOTIFICATIONS = properties_handler(1)


if __name__ == '__main__':
    user = User()
    user.IS_VERIFIED(True)
    assert(user.IS_VERIFIED())
    assert(not user.RECEIVE_NOTIFICATIONS())

    user.IS_VERIFIED(False)
    user.RECEIVES_NOTIFICATIONS(True)
    assert(not user.IS_VERIFIED())
    assert(user.RECEIVE_NOTIFICATIONS())

В принципе, код вполне себе понятный, но если есть какие-либо вопросы — с радостью отвечу на них в комментариях. Вы можете заметить, что конкретно эту имплементацию можно улучшить: использовать свойства вместо обычных методов, не возвращать ничего при установке бита и т. д. Я с этим согласен, но эта заметка не про конкретную реализацию, а про общий подход.

По теме:

Google I/O 2009

5/24/2009

В среду и четверг я буду на конференции Google I/O. Вроде все доклады, на которые хочу сходить, выбрал и занес себе в календарик. Хотя одна дыра всё таки осталась, но её заполню уже на месте. Очень жду V8: Building a High Performance JavaScript Engine и Even Faster Websites.

Кремниевая Долина

5/19/2009

Palo Alto CalTrain station

Создал на фликре коллекцию, куда буду складывать фотографии из Кремниевой Долины. Пока выложил Гуглплекс, Стэнфордский университет и кусочки маленьких американских городков.

Изнутри офисы Гугла мне посмотреть не удалось, потому что я там был проездом, а у них без знакомого сотрудника внутрь не пускают. Как найду кого-нибудь, кто согласится устроить мне тур, так и посмотрю (хотя коллеги по работе говорят, что ничего особенного внутри нет — офисы, как офисы; но всё равно интересно).

Стэнфорд — огромный университет (все красные крыши на фотографиях — здания университета), по территории разбросаны скульптуры Родена, бегают белки и студенты.