About Blog Dev | Alfa Romeo SZ Conkeror wishlist

All articles, tagged with “python”

Hgshelve

Few days ago there was a lot links on the Internet to gitshelve, which implements persistent versioned storage of objects in the git. I’ve read it description and realized that there are few serious design flaws:

  • Can store only strings
  • Uses subprocess.PIPE for interconnection with git
  • Uses bunch of C+Perl+Shell code in Python library instead of using another Python library ;-)
 continue reading

Exception #08

Итак, 24 мая опять намечается тусовка питонистов! ;-) Что хорошо — у Ивана получилось, как он и обещал, устроить это всё через пару месяцев. А что отлично — что это будут мастерклассы. Три штуки.

Меня лично больше всего интересует Twisted, как наиболее далёкая для меня сейчас из всей троицы вещь. ;) А вот трюки… сделать тут интересный и полезный доклад реально сложно. Ну посмотрим, что получится.

В общем, главное — приходите! Семинар крут не только своими докладами, но и тусовкой после завершения. =)

render_to improved

[UPD от 12 ночи]

Чуть больше года назад, когда меня окончательно задолбало писать render_to_response c кучей параметров, я себе написал маленький декоратор render_to, который заметно уменьшал количество писанины.

Но вот не так давно обсуждали его в джаббер-конференции pythonua@c.j.r (кстати, официальная конференция python.com.ua), где появилась идея слегка его проапгрейдить до возможности задавать темплейт из view (когда одна вью может выдавать различные странички). В принципе, идея усложнения декоратора мне не особенно нравится (да и потом, кому надо — может переделать себе, благо несложно), но по размышлении я увидел, что особенного усложнения нету, плюс сохраняется обратная совместимость полностью (что важно, потому как мне есть и где использовать новую фичу, но не очень хочется ломать все вьюхи, использующие старую версию ;).

 continue reading

Exception #07

Итак, после полугодового перерыва - Exception опять с нами. В этот раз в расширенном формате (два зала с параллельными докладами) и не только про питон (хех, про Ребол - это точно интересно :).

Так что, господа, устремляемся регистрироваться! :-)

P.S.Хорошие новости - дальше всё войдёт в ритм раз в два месяца.

ImprovedImageField

В процессе работы над одним проектом я в очередной раз столкнулся с тем, что джанговский ImageField меня ну никак не устраивает — в нём отсутствует возможность ресайза при аплоаде, некак загружать картинки в разные директории1, кроме как по дате, ну и динамически назвать файлик2 тоже нельзя.

 continue reading

Пользователь и его профиль

Известная штука, что у Django есть статическая (неизменяемая официально поощряемыми путями) модель User и костыль для дополнительных полей (которые может каким-либо образом использовать приложение) в виде настройки USER_PROFILE, указывающей на модельку-профиль. В результате использования такого костыля, если не делать дополнительных телодвижений, количество запросов возрастает (пример для данного блога, где каждому комментирующему ставится ссылка на его сайт) на число комментариев (даже не комментировавших, а комментариев!).

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

Потому, после продолжительных колебаний и сомнений, я решил сделать всё радикальнее - удалить всю модель UserProfile, применив вместо неё monkey patching к стандартной модели:

User.add_to_class('site', models.URLField(verify_exists=False, blank=True))
User.add_to_class('email_new', models.EmailField(blank=True))

User._meta.admin.fields += (
    ('Byteflow Extensions', {'fields': ('site', 'email_new')}),
    )

Конечно, главная проблема здесь - это то, что способ совершенно не стандартный и вряд ли кто-то будет ожидать, что табличка auth_user будет меняться. Но такой способ настолько выгоднее и удобнее, что я решил наплевать на эти трудности. :-)

И ещё одно - спасибо Амиту, который и показал конкретно, как это сделать. ;-)

Сортировка почты

Настраивал себе локально чтение почты (кое-какие потоки почты забираю вместо перенаправления на гмейл, проще жить выходит :-), ну и сортировку соответственно. Так как я не слишком люблю клиенты типа Тандербёрда или Сильфид, то основным способ у меня всегда был procmail. Но его правила порядочно раздражают: читаешь доки, читаешь, проходит три месяца - и всё забывается. :-) Ещё, пока читал почту Gnus’ом, фильтровал его внутренними правилами, которые конечно поинтереснее прокмейловых, но… привязаны к Гнусу.

Потому я решил поискать для себя что-то стороннее, но поинтереснее прокмейла. maildrop, имя которого раньше неоднократно встречал, не впечатлил синтаксисом. Промелькнула даже шальная мысль попробовать раскидывать почту правилами Exim’а, но это было бы ничуть не более портабельное решение, чем правила Гнуса.

Пересмотрел порядка десятка программ и наткнулся на очень интересную штуку - maildirproc. Самое большое её достоинство: она написана на питоне и правила раскидывания - тоже самый обычный питон, можно творить всё, что душе угодно. Кроме того, есть одна особенность - в отличии от MDA типа procmail’а и maildrop’а, эта штука ориентирована сугубо на сортировку почты для одного человека. Потому просто указывается место, где появляется почта (типа /var/mail/piranha), и программа делает с каждым пришедшим письмом разные непотребности в полном соответствии правилам (есть однократный запуск, когда раскидывается вся текущая почта, и постоянный, когда “почтовые места” проверяются ежесекундно).

Работает всё очень просто - программа входит в бесконечную итерацию, в каждый проход которой существует объект письма, над которым можно поиздеваться. Пример настройки можно посмотреть тут (совсем простой вариант, но там рядом есть ещё несколько вплоть до совершенного хардкора), все возможности можно увидеть здесь.

JSON в куках

В принципе, идея лежит на поверхности: JSON - такой формат, который легко понимается и серверными языками, и джаваскриптом, и часто человеком. Потому хранить какие-то маленькие кусочки информации в виде словаря в одной куке бывает очень даже удобно.

Но есть один момент, который будет неочевиден любому, кто не сильно часто сталкивается с джаваскриптом и вообще особенностями разных браузеров (к примеру, мне ;-) - обязательная экранизация строк. Так, как они экранизуются в урлах. А то FF и IE нормально воспринимают, а Опера и Сафари - нет. ;-)

Напоминание, на всякий случай: в Python для этого есть urllib.quote и unquote, а в JS - escape и unescape.

Пробелы в Питоне

Нашёл отличную статью Оливера Фромме про пробелы и отступы в Питоне. Рекомендуется к прочтению, особенно противникам Питона.

Пара слов о декораторах

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

def render_to(tmpl):
    def renderer(func):
        def wrapper(request, *args, **kw):
            output = func(request, *args, **kw)
            if not isinstance(output, dict):
                return output
            return render_to_response(tmpl, output, 
                   context_instance=RequestContext(request))
        return wrapper
    return renderer

Конечно, можно дописать пару строк к возврату враппера и получить в принципе работающий механизм:

        wrapper.__name__ = func.__name__
        wrapper.__doc__ = func.__doc__
        return wrapper

Но на самом деле это не самый красивый метод. Куча всяких руководств для начинающих по написанию декораторов всегда рекомендует юзать модуль Мишеля Симионато - decorator. В принципе, всё конечно просто отлично, но есть у него огромный недостаток - это дополнительная библиотека, в то время как есть отличное решение из стандартной библиотеки - functools.wraps. Его использование ничем не отличается от использования decorator‘а:

from functools import wraps

def render_to(tmpl):
    def renderer(func):
        @wraps(func)
        def wrapper(request, *args, **kw):
            output = func(request, *args, **kw)
            if not isinstance(output, dict):
                return output
            return render_to_response(tmpl, output, 
                   context_instance=RequestContext(request))
        return wrapper
    return renderer

И всё становится белым и пушистым. :-) Один момент непонятен - почему его не пишут во всех этих руководствах для начинающих? Ведь эти начинающие с течением времени становятся продолжающими и точно так же не знают о простой и приятной штуке прямо в stdlib‘е.