2015-03-25

Piter Py #2 — не про доклады и взгляд в будущее

Piter Py #2

Piter Py #2 завершен. Было много интересных докладов, интересные гости, но главное — было много полезного и приятного общения.

Да, иногда общение на конференциях оказываетя полезнее самих докладов. А еще, кроме докладов, очень важно чтобы конференция была организована так, чтобы недочеты организаторов, а без них не бывает, не беспокоили участников.

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

Приятные мелочи

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

Были еще бесплатные блокноты, но они были не на виду и многие не смогли ими воспользоваться, хотя могли бы.

Неплохо смотрелась твиттер-стена.

Очень хорошо

Как и в прошлый раз, питание для участников было обеспечено по высшему разряду. Прекраснейший "шведский стол" в обед. Во многом это, конечно, заслуга Original Sokos Hotel Olympia Garden, потому что участнкиам конференции просто был доступен стандартный обед этой гостиницы. Хотелось бы чтобы эта особенность конференции не изменилась, если придется поменять место проведения конференции.

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

Piter Py #3

Конечно, на самом деле, Piter Py #2 еще не совсем завершился: будет еще выложено видео всех докладов, будут еще обзоры в блогах и обсуждения в сообществах, например, на встречах Saint-Petersburg Python Interest Group.

Однако, сейчас надо уже посмотреть в будущее и отметить для себя "по горячим следам" что нужно ни в коем случае не потерять и что хотелось бы сделать лучше.

Не потерять

  • Качественный подбор докладчиков
  • Почти все доклады читаются на PiterPy впервые
  • Отличная еда и вкусный кофе
  • Посиделки за большим столом после конференции
  • Серьезные спонсоры
  • Традиционные значки PiterPy

Улучшить

  • Обязательно опубликовать программу полностью за месяц до конференции или раньше
  • Сделать два дня, а лучше три:)
  • Больше сильных англоязычных докладчиков
  • Обеспечить синхронный перевод на английский всех докладов
  • Провести какие-то мероприятия, кроме докладов (кодеджемы, тренинги для новичков)
  • Активно отслеживать освещение конференции в социальных сетях и участвовать в этом
  • Сделать собственный сайт конференции

2015-03-24

Если б не было зимы…

Мне тут подумалось, а что если бы не было Python-а, на чем бы я писал? А потом я подумал: "а что если бы не было Linux?" И понеслось…

Если б не было Python… я бы писал на Java.
Если б не было Linux… я бы писал на C#.
Если б не было Windows… я бы писал на Objective-C.
Если б не было iOS… я бы писал на C++.
Если б не было MacOS… я бы писал на Python.
Если б не было Fortran… я бы писал на BASIC.
Если б не было C… я бы писал на Assembler.
Если б не было BASIC… я бы писал на C.
Если б не было ZX Spectrum… я бы стал физиком.

2013-09-12

Агрегатор систем контроля версий, aka "workspace configurator"

Когда-то я работал с Subversion, потом стал работать с Git-ом. Git удобен и очень грамотно работает с кодом. Но все его возможности в реальной разработке разбиваются о потребности более высокого уровня.

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

Поэтому уже пару лет я хожу с идеей конфигуратора рабочего пространства. Буду рад, если у меня все-таки дойдут руки это сделать…

Задача

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

Требования

  • Сопоставление любой папки или файла в проекте, в том числе корневой, любой папке или файлу произвольного репозитория.
  • Единый интерфейс отслеживания изменений и управления ветками.
  • Транслирование изменений и веток в соответствующие системы контроля версий.
  • Использование различных алгоритмов отслеживания изменений, а именно:
    • Standard - в обе стороны;
    • Library - только обновления из репозитория в проект;
    • Upstream - обновления из репозитория + версионированные патчи проекта;
    • Publish - только из проекта в репозиторий;
    • Fixed - закрепление кода в определенной версии.
  • Поддержка перекрытия одной папки несколькими репозиториями.
  • Отслеживание изменений и веток конфигурации рабочего пространства в отдельном репозитории.
  • Возможность исключить установленное соответствие с репозиторием при создании ветки конфигурации.
    • Инициализация рабочего пространства из конфигурационного репозитория.

    Существующие решения

    Ни одно из существующих решений не удовлетворяет требованиям полностью. Наиболее близки по идеологии "google repo" и "perforce".

    svn externals

    • Только для Subversion.
    • Нет перекрытия репозиториев в одной папке.
    • Изменения и ветки внешнего репозитория отслеживаются отдельно.

    git submodules

    • Только для Git.
    • Изменения и ветки внешнего репозитория отслеживаются отдельно.
    • Не отслеживаются обновления внешнего репозитория.

    git subtree

    • Только для Git.
    • Поддерживается только механизм перекрытия папок.
    • По сути - набор хаков через низкоуровневый интерфейс git.

    google repo

    • Только для Git.
    • По умолчанию работает по алгоритму "Standard".
    • Отступление от стандартного алгоритма требует работы с конкретными репозиториями.
    • Идейно наиболее близкое к задаче решение.

    perforce git fusion

    • Только для Git.
    • Удобный механизм управления из Perforce.
    • Интеграция с Perforce.
    • Проприетарное решение.

    hg subrepository

    • Поддержка Mercurial, Subversion, Git.
    • Не отслеживаются обновления внешнего репозитория.
    • Изменения и ветки внешнего репозитория отслеживаются отдельно.
    • Не рекомендовано к использованию (feature of last resort).

    Сценарии использования

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

    1. Проект в Git и публикация части во внешний SVN

    Андрей поддерживает в SVN большой многокомпонентный продукт Alpha.
    Борис разрабатывает в Git компонент Beta продукта Alpha.

    Ветка Beta/master должна публиковаться в ветку Alpha/beta, причем для папок должны выполняться следующие соответствия (слева git beta, справа svn alpha):
        /src -> /scripts/beta
        /tests -> /tests/beta
        /doc/src -> /doc/src/beta

    Для решения задачи Борис создает такую конфигурацию рабочего пространства:
        / -> git beta - branch master
        /src -> svn alpha - /scripts/beta - mode publish - skip branching
        /tests -> svn alpha - /tests/beta - mode publish - skip branching
        /doc/src -> svn alpha - /doc/src/beta - mode publish - skip branching

    2. Проект в Git, внешняя библиотека в Git и собственные патчи

    Андрей разрабатывает в Git проект Alpha.
    Борис разрабатывает в Git библиотеку Beta.

    Андрей сделал исправления в библиотеке Beta и предложил их Борису для внесения в основной репозиторий. До тех пор, пока Борис не внесет исправления в библиотеку Beta, Андрей вынужден накладывать свои исправления поверх всех обновлений библиотеки Beta.

    Для решения задачи Андрей создает такую конфигурацию рабочего пространства:
        / -> git alpha
        /ext/beta -> git beta - branch stable - mode upstream
    При этом инструмент управления рабочим пространством автоматически отслеживает все изменения, которые Андрей сделал в Beta и накладывает их поверх стабильной ветки этой библиотеки.

    2011-08-18

    Еще один велосипед для Django

    Вчера выложил в открытый доступ под лицензией BSD свой новый велосипедик для Django.

    Называется творение "django-supergeneric". Исходный код доступен тут: https://github.com/lig/django-supergeneric

    Причиной написания этого стало желание перестать постоянно писать одно и то же. Почти всегда для каждой модели приходится писать похожие друг на друга, как близнецы-братья, view для просмотра списка объектов, одного объекта, создания объекта, редактирования объекта и удаления объекта. Понятно, что есть generic views, но их тоже надо конфигурировать, причем многие параметры повторяются. Да, и каждый раз для всех пяти view надо прописать urlpatterns, которые тоже для всех объектов очень похожи.

    Вот поэтому и появился django-supergeneric.

    Пример использования можно посмотреть в демо-проекте: https://github.com/lig/django-supergeneric/tree/master/project

    Upd: страничка на ohloh: https://www.ohloh.net/p/django-supergeneric, плюсуйте, кто будет пользоваться, если не лень.

    2010-12-22

    Пам-парам, по "монгам"

    Пару месяце назад я начал активно использовать MongoDB как для своих открытых проектов, так и по работе. Надо сказать, что этот относительно кратковременный опыт весьма и весьма положительный.

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

    В основном я использую MongoDB из Python, для чего использую PyMongo напрямую или MongoEngine (подобие ORM для MongoDB с несколькими фишками для использования его с Django). И вот как раз с взаимодействием с MongoDB из Python-а и связаны пара подводных камушков. Точнее с параллельным использованием JavaScript встроенного в MongoDB и PyMongo.

    Вообще говоря, "питоновский" тип DateTime прекрасно обрабатывается MongoDB. Внимательный читатель документации сразу обратит внимание (я этого не сделал), что PyMongo нужно передавать дату/время в UTC, т.е. нужно использовать datetime.utcnow(), а не привычное большинству datetime.now(). Это первый подводный камень, который, впрочем, вполне очевиден и в явном виде отражен в документации.

    Есть еще один подводный камень связанный с хранением времени. Предположим, что, по каким-то причинам, мы хотим хранить время в формате unixtimestamp, т.е. вещественное количество секунд прошедших с 1.01.1970 с тремя знаками после запятой или даже просто целым числом. Это может быть нужно чтобы упростить и ускорить запись журнала каких-либо событий в MongoDB. Пока мы работаем с этими числами через PyMongo, все хорошо. Но потом встает необходимость оперировать с этим значением времени из функции JavaScript, например, при выполнении операции Map/Reduce или просто в консоли MongoDB. Пусть в базе лежит такой документ (timestamp получен сейчас, т.е., как минимум, в 2010 году):
    
    { "_id" : ObjectId("4d125e16f52cb12e01d5d041"), "timestamp" : 1293038527, "name" : "jump" }
    
    
    Пусть нам нужно получить год, месяц и число, в который произошло событие. Вот с чего начал я:
    
    db.events.find().forEach(function (event) {
      var date = new Date(event.timestamp);
      print(date.getFullYear(), date.getMonth(), date.getDate());
    })
    
    
    Какого же было мое удивление, когда я увидел в ответ "1970 0 16", т.е. нулевой (!) месяц и всего 16-й день от начала эпохи. Чтение документации по JavaScript Date Object открыло мне глаза прежде всего на то, что в JavaScript timestamp - это целое число миллисекунд прошедших от начала эпохи. И код превратился в такой:
    
    db.events.find().forEach(function (event) {
      var date = new Date(event.timestamp * 1000);
      print(date.getFullYear(), date.getMonth(), date.getDate());
    })
    
    
    Этот код вернул уже "2010 11 22", но сегодня 22.12.2010. Да, да, да, вспоминаем нулевой месяц. Из той же документации по JavaScript Date Object я узнаю, что, оказывается, именно месяц считается в JavaScript начиная с нуля (зачем???), тогда код приобретает окончательный вид:
    
    db.events.find().forEach(function (event) {
      var date = new Date(event.timestamp * 1000);
      print(date.getFullYear(), date.getMonth() + 1, date.getDate());
    })
    
    
    Теперь ответ правильный: "2010 12 22".

    На сегодня, думаю, этого достаточно. В следующий раз поделюсь опытом использования MapReduce в MongoDB. Покажу как возвращать из Reduce списки значений и какого подхода к расчету значений в Reduce следует избегать.

    2010-12-20

    Git mass push. Как заслать во все "ремоуты".

    Думаю, все, кто работал с git-ом, сталкивались с ситуацией, когда удаленных репозиториев несколько и хотелось бы сделать "git push" во все. Например, у меня проекты лежат одновременно на sf.net, github.com и в собственном приватном хранилище.

    Я для себя написал маленький скриптик на bash:
    #~/bin/bash
    git remote show | while read repo_name
    do
    git push $repo_name $*
    done
    Постоянная ссылка на этот кусок кода: http://paste.nophp.ru/1Nu. Код раскрашен с помощью Paste.NoPHP.ru.
    Если положить скрипт в файл "~/bin/git-mass-push", то его можно будет запускать командой "git mass-push", для которой будет работать стандартное автодополнение git-а. При этом, этой команде можно передать любые параметры, которые принимает "git push" после имени репозитория, что видно из кода.

    Пользуемся, радуемся;)