A shelter from pigs on the wing
DMZ
дневник заведен 09-08-2004
постоянные читатели [32]
3 CaHuTaPa, 517design, Arde, Art`Is, aviabaza, BlackDrago, CyberJoe, DeadMorozz, Depeche Mode, DMZ, d_r, Ewige, glv12 Marla Zinger, goldenandy, Grimble, Hydralisk, Jude, Katrine Himitsu, Leave-me-alone, MISTIK, My3a, Nash, Nicholas Hawkwood, Pingvin, Riskoff, VorteX DrAgON, Wolfram, Букля_, достало, Муть, Рика, Эль
закладки:
цитатник:
дневник:
местожительство:
Красноярск, Россия, Сибирь
интересы [24]
программирование, C++, Depeche Mode, Star Wars, perl, DVD, JavaScript, FAR, lost, 80е, Half Life 2, долго спать, Miami Vice, веб-роботы, кентаврицы
антиресы [9]
грибы, грейпфрутовый сок, мёртвые люди, табличка обед, долго спать
Понедельник, 4 Июля 2011 г.
05:24
Как показывает опыт, проще за 20 минут поднять с нуля виртуалку с Ubuntu-ой, чем пытаться настроить Windows для веб-разработки (хотя и такое возможно). Многоядерные процессоры с виртуализацией и дешевая оперативная память здесь очень даже к месту.

Четверг, 30 Июня 2011 г.
10:30
Производительность труда зависит, в том числе, и от размера шрифты, цветовой гаммы и от того, что Java Swing не дружит с нативными оконными интерфейсами.

Вторник, 28 Июня 2011 г.
08:08 Django и ODF (ODS, ODT)
Вроде OpenOffice весь из себя формат открытый-преоткрытый, свободный-пресвободный, но функциональной библиотеки для генерации документов я не нашел. Нужный функционал только в самом OpenOffice, к которому можно цепляться по сетевому протоколу.

Но на наше счастье внутри ODF сидит обычный xml (плюс пара файлов и все это обернуто в zip).

Поэтому результат вышел даже лучше чем планировал.

  • Шаблон документа можно подготовить в самом openoffice;
  • Распаковать odf-документ, извлечь content.xml;
  • подстановку переменных и повторение строк можно поручить обычным таким шаблонам django;
  • собрать zip-файл с content.xml, блэк-джеком, манифестом и mime можно на лету средствами стандартной библиотеки python;
Личный профит: шаблоны можно теперь не рисовать самому, а поручить кому-нибудь другому

Теперь надо обкатать технологию и попробовать как-нибудь скрестить с генерацией PDF

В копилку валидатор, который помог в отладке.

Четверг, 16 Июня 2011 г.
11:45
Ради соблюдения DRY-принципа в ход пошли уже метаклассы.

Зато если что теперь и поломается, то строго в одном месте.

Пятница, 10 Июня 2011 г.
07:20
Основная опасность в Django при создании чего-нибудь более крупного, чем сайт визитка — это возможность увлечься метапрограммированием, вместо создания полезного кода. Тем более, что Python с его богатыми ООП и интроспекцией этому только способствует.

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

Но не в условиях дедлайна. Хотя еще остается шанс «день потерять, зато за час долететь», на что я и надеюсь, посвятив уже целые рабочие сутки на рефакторинг форм, написание абстрактных фабрик классов и хитрых примесей.

Четверг, 9 Июня 2011 г.
07:42 PyCharm
Еще до того как в NetBeans 7 вырезали поддержку Python (потом добавили плагином, который лежит еще где-то в dev-репах) я перестал им пользоваться. Уж больно тяжелая эта Java

Но gedit, конечно, хорошо, но как минимум грамотного рефакторинга, быстрого перехода между файлами и других не таких уж мелочей там не хватало.

И тут я скачал и попробовал PyCharm, благо у него 30 дней пробного срока имеется.

По описанию, IDE резко заточено под Python и, что самое приятное, поддержка Django у них тоже приоритетна. После двух дней становится ясно, что надо брать. Есть и рефакторинг и переход между вьюхами-шаблонами, классами-суперклассами, импорт, автозаполнение параметров функций, методов, шаблонных тегов и всего остального, подсветка ошибок. Распознает модели django, в том числе как и явно указанные поля, так и то, что появляется по FK/m2m связям из RelatedManager.

И наконец-то я могу дебажить Python, а не разбрасывать assert-ы где попало

Наверняка еще много чего полезного там есть. За два дня не найдешь всего.

Конечно, опять Java и уже почти 700Mb оперативы и с хинтингом шрифтов Java на Линуксе не хочет дружить, но пока плюсы перевешивают

Начальству обрисовал цель, что неплохо бы заиметь коммерческую лицензию.

Кроме того у них есть PhpStorm для PHP, WebStorm для HTML, RubyMine для Ruby и Rails, IDEA для Java (и Android из коробки) и IDEA Ultimate, где есть все осразу и дешевле чем по отдельности.

Понедельник, 23 Мая 2011 г.
10:48
Я по наивности думал, что на django нельзя писать говнокод. Оказывается можно.

Среда, 23 Марта 2011 г.
11:35 django 1.3


Вот почти только что пони принесла релиз 1.3 с весьма интересными нововведениями.

Надо будет поизучать и то, что понадобится, применить. По мере изучения напишу что-нибудь

Вторник, 22 Февраля 2011 г.
08:11 DOC / RTF / ODT / ... -> HTML / PDF / DOC / ODT / RTF / ...
Немного рабочих моментов и полезного кода. Может кому пригодится.

Конвертируем все что угодно в что-то другое с помощью OpenOffice/LibreOffice. Понадобилось тут автоматизировать наконец это дело.

Первая рабочая версия. Дальше уже можно пилить по вкусу.

Принцип работы — uno. Первый раз слышу. Похоже на COM в Windows. Запускает OpenOffice в фоне и общается с ним по TCP.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# -*- coding: utf-8 -*-
#!/usr/bin/env python
# Copyright (C) 2011 DMZ <dmz @the-island.ru>
# Licensed under the GNU LGPL v2.1 - or any later version.
 
from ooutils import oo_properties as oop, OORunner
from optparse import OptionParser, OptionValueError
import sys
import re
import os
 
from unohelper import systemPathToFileUrl
from com.sun.star.beans import PropertyValue
 
# http://wiki.services.openoffice.org/wiki/Framework/Article/Filter/FilterList_OOo_3_0
CONVERT = {
    'html': 'HTML (StarWriter)',
    'xhtml': "XHTML Writer File",
    'rtf': "Rich Text Format",
    'doc': "MS Word 97",
    'odt': "StarOffice XML (Writer)",
    'pdf': "writer_pdf_Export",
}
 
def read_format(option, opt, value, parser):
    value = value.lower()
    if value not in CONVERT:
        formats = ', '.join(CONVERT.keys())
        raise OptionValueError(
            'Формат вывода не поддерживается. Доступные форматы: %s' % formats)
    setattr(parser.values, option.dest, CONVERT[value])
 
if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option('-i', '--input', dest='input')
    parser.add_option('-o', '--output', dest='output')
    parser.add_option('-f', '--format', action='callback', type='string',
        callback=read_format, dest='format', default=CONVERT['html'])
    (options, args) = parser.parse_args()
 
    if not options.input:
        print >>sys.stderr, u"Укажите месторасположение входящего файла (-i)"
        sys.exit(1)
 
    if not options.output:
        print >>sys.stderr, u"Укажите месторасположение итогового файла (-o)"
        sys.exit(1)
 
    odir = os.path.dirname(options.output)
    if not os.path.isdir(odir):
        print >>sys.stderr, u"Путь для сохранения (%s) не существует" % odir
        sys.exit(1)
 
    if not os.path.isfile(options.input):
        print >>sys.stderr, u"%s: Указанный файл не существует" % options.input
        sys.exit(1)
 
    oor = OORunner()
    desktop = oor.connect()
 
    document = desktop.loadComponentFromURL(systemPathToFileUrl(options.input),
        "_blank", 0, oop(ReadOnly=True, Hidden=True))
 
    print u"Сохраняем документ в %s" % options.output
 
    document.storeToURL(systemPathToFileUrl(options.output),
        oop(Overwrite=True, FilterName=options.format))
 
    document.close(True)
    oor.shutdown()
ooutils можно взять тут и сохранить в отдельный файл (положить или в папку со скриптом или в питоновские пути)

Фикс для нахождения LibreOffice (amd64):

1
2
3
4
# Find OpenOffice.
    _oopaths=(
        ('/usr/lib64/libreoffice/program', '/usr/lib64/libreoffice/program'),
     )
Пример:

1
python o2o.py -i document.odt -o document.pdf -f pdf
Пятница, 3 Декабря 2010 г.
10:35 Овсянка, сэр!
Халява для разработчиков от Microsoft. Причем есть даже очень интересные предложения.

А еще оказалься, что fiddler — это теперь их рук дело.

Понедельник, 22 Ноября 2010 г.
09:55
Пока не вышла Opera 11 решил пожить на Chrome (и на работе и дома). Пока нравится. Часть отсутствующего (но нужного) функционала решилась расширениями. Заодно в рамках изучения новых технологий покапался в Extensions API, может что на практике пригодится.

Среда, 4 Августа 2010 г.
09:06 PHP ODT
По политическим мотивам пришлось переписывать кусок кода по генерации документов. Вместо PDF надо делать ODT.

Но нет худа без добра. Нашел отличную библиотечку по форматированию ODT. Основной плюс в том, что можно подготовить шаблон в самом OpenOffice вместе со всем форматированием, свойствами, защитой, а потом прогнать шаблон через библиотеку. В итоге все намного проще и легче (даже и по загрузке сервера), чем генерация PDF.

Конечно, немного пришлось пофиксить код, а то из коробки он не завелся. Благо GPL.

В итоге и начальство довольно, и мне куча экспы перепало.

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

Вторник, 3 Августа 2010 г.
00:35
Сегодня я узнал о Python PEP342. Нужно срочно найти этой фиче какое-нибудь интересное (и практическое) применение

Четверг, 17 Июня 2010 г.
14:59

И снова про освоение новых рубежов

Как написать на python веб-приложение с минимальной начинкой фреймворков? Ну чтобы не генерировать кучу оберточного кода для простого 'Hello World'?

Вроде в nginx так и не допилили поддержку WSGI, чтобы раз! и поставился из репов. Надо патчить руками.

Вообще-то можно было сделать даже чистый wsgi + apache/mod_wsgi, но так как апач всё равно спрятан глубоко за nginx и приложение простое и некритичное, то решил в качестве прослойки попробовать что-нибудь новое

Понедельник, 14 Июня 2010 г.
23:11 sphinx
В рамках внезапного ежемесячника изучения новых технологий прикрутил поиск на sphinx к существующему сайту на django+pgsql

Вроде даже работает

Четверг, 10 Июня 2010 г.
19:04 Еще один гвоздь
Попробовал Google App Engine.

Перетащил туда текущее python-приложение. Вроде даже работает как ни в чем не бывало.

16:28 Yahoo Pipes
Yahoo Pipes, если залезть поглубже — штука очень отличная.

  • Запросить от пользователя параметр
  • Собрать из него ссылку
  • Скачать HTML страницу
  • Разбить на блоки
  • Вытащить регэкспом из блока кодовое слово
  • Из кодового слова каждого блока создать два URL: ссылки на RSS-фиды
  • Скачать каждый фид
  • Слить в один фид
  • Отсортировать по времени
  • Оставить только 100 первых элементов
А еще учесть, что все работает очень быстро, есть встроенное кэширование и прочие радости. И подумать сколько времени я бы это писал и отлаживал на python.

А еще графический интерфейс. Никакого кода. Одно из самых гениальных изобретений человечества.


Среда, 9 Июня 2010 г.
08:24
Я все таки запилил на хабр статью о скробблинге музыки из mpd через официальный клиент. Так что можно ставить плюсики или минусики

Вторник, 8 Июня 2010 г.
11:32 node.js
Надо бы написать что-нибудь полезное на node.js. И посмотреть насколько оно интереснее twisted.

Предпочитаю осваивать новые технологии на практике

Среда, 2 Июня 2010 г.
19:34 Python GTP
Давно не выкладывал полезного ненужного кода...

Питоний модуль для вытаскивания исполнителя/названия трека из gpt/gp3/gp4/gp5 файлов

Основа нашлась в глубинах Google Code Search, а потом опробована на over 9000 файлов из несортированной свалки. А там были файлы, наверное, всех версий. Ну кроме шестой, конечно

Лицензия — BSD, все дела

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import struct
import sys
from locale import getpreferredencoding
class NotGPFile(Exception):
    pass
 
class GuitarProFileSimple(object):
    _encoding = getpreferredencoding()
 
    def read_long_string(self, fo):
        s = fo.read(4)
        size = struct.unpack('l', s)[0]
        s = fo.read(1)
        if size == 0:
            size = ord(s)
 
        string = fo.read(size - 1)
 
        return string.decode(self._encoding)
 
    def read_byte_string(self, fo):
        s = fo.read(1)
        size_block = ord(s)
        s = fo.read(1)
        size_string = ord(s)
 
        string = fo.read(size_string)
 
        fo.read(size_block - size_string - 1)
 
        return string.decode(self._encoding)
 
    def __init__(self, fo):
        fo.seek(0)
 
        head = fo.read(20)
 
        header_len = 0
        if head[1:19] == "FICHIER GUITAR PRO":
            header_len = 19
            fo.read(1)
 
        if head[1:20] == "FICHIER GUITARE PRO":
            header_len = 20
            fo.read(2)
 
        if header_len:
            self.version = fo.read(4)
            hsize = ord(head[0])
            fo.seek(hsize + 5 + 1)
 
            if self.version in ['1T\x03\x04']:
                fo.read(3)
                title = self.read_byte_string(fo)
                subtitle = ''
                artist = self.read_byte_string(fo)
            elif self.version in ['1.04', '1.02', '1.03']:
                title = self.read_byte_string(fo)
                subtitle = ''
                artist = self.read_byte_string(fo)
            elif self.version in ['2.21']:
                fo.read(1)
                title = self.read_byte_string(fo)
                subtitle = ''
                artist = self.read_byte_string(fo)
            else:
                fo.read(1)
                title = self.read_long_string(fo)
                subtitle = self.read_long_string(fo)
                artist = self.read_long_string(fo)
 
            if title:
                if subtitle:
                    self.title = '%s (%s)' % (title, subtitle)
                else:
                    self.title = title
            else:
                if subtitle:
                    self.title = title
                else:
                    self.title = ''
 
            self.artist = artist or ''
 
            return
 
        raise NotGPFile(u'Not a GP file')
Закрыть