<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6428567201714816130</id><updated>2024-10-12T01:13:06.754+03:00</updated><category term="python"/><category term="PyQt"/><category term="Qt"/><category term="SQL"/><category term="model-view"/><category term="модели Qt"/><category term="модель-представление"/><category term="GUI"/><category term="must have"/><category term="recipes"/><category term="sqlite"/><category term="интерфейс"/><category term="рецепты"/><category term="NCReport"/><category term="PyNCReport"/><category term="repgen"/><category term="report generator"/><category term="ui"/><category term="внешний ключ"/><category term="генератор отчетов"/><category term="инструмент"/><category term="метаданные"/><category term="отчеты"/><category term="сборка"/><category term="MDI"/><category term="Phonon"/><category term="PyWin32"/><category term="audio"/><category term="automation"/><category term="cron"/><category term="crontab"/><category term="math"/><category term="refactoring"/><category term="sceduler"/><category term="unittest"/><category term="аудио"/><category term="виртуализация"/><category term="воспроизведение"/><category term="диалог"/><category term="дублирование кода"/><category term="звук"/><category term="крон"/><category term="кронтаб"/><category term="маппинг виджетов"/><category term="планировщик"/><category term="тестирование"/><title type='text'>class QSqliteBlog(QObject):</title><subtitle type='html'>Блог в первую очередь для себя, для сохранения сакральных знаний о питоновских и иже с ними граблях, плюшках и т.п. Хотя, если еще кому-то окажется полезным, буду только рад.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-6999372422782546727</id><published>2013-02-19T10:36:00.000+04:00</published><updated>2013-02-19T10:36:16.199+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="NCReport"/><category scheme="http://www.blogger.com/atom/ns#" term="PyNCReport"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="repgen"/><category scheme="http://www.blogger.com/atom/ns#" term="report generator"/><category scheme="http://www.blogger.com/atom/ns#" term="генератор отчетов"/><category scheme="http://www.blogger.com/atom/ns#" term="отчеты"/><category scheme="http://www.blogger.com/atom/ns#" term="сборка"/><title type='text'>Ограничения пробной версии NCReport</title><summary type="text">К моему удивлению, появился некоторый интерес к моему старому посту о PyNCReport. При этом возник вопрос об ограничениях пробной версии, доступной для скачивания, и просьба показать использование PyNCReport на примерах. Примеры я приведу в отдельной статье позднее, а про лицензирование NCReport исследование провел. Итак.

На сайте производителя nocisoft.com доступны для скачивания сам NCReport </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/6999372422782546727/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2013/02/ncreport.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/6999372422782546727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/6999372422782546727'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2013/02/ncreport.html' title='Ограничения пробной версии NCReport'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-4405107157649987537</id><published>2012-12-26T18:29:00.001+04:00</published><updated>2012-12-26T18:29:25.974+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="recipes"/><category scheme="http://www.blogger.com/atom/ns#" term="рецепты"/><title type='text'>Рецептики: Определить все загруженные модули</title><summary type="text">Спросили на ответах Гугла. Не мудрствуя лукаво, нашел решение на stackoverflow.com и сделал его немного более pythonic:
import types
imports = dict((name, val) for name, val in globals().items() if isinstance(val, types.ModuleType))
На Python 2.7 можно немного изящнее:
import types
imports = {name: val for name, val in globals().items() if isinstance(val, types.ModuleType)}

Однако видим пример </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/4405107157649987537/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2012/12/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/4405107157649987537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/4405107157649987537'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2012/12/blog-post.html' title='Рецептики: Определить все загруженные модули'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-1319172532298750584</id><published>2011-12-01T13:39:00.001+04:00</published><updated>2012-12-26T13:49:07.273+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cron"/><category scheme="http://www.blogger.com/atom/ns#" term="crontab"/><category scheme="http://www.blogger.com/atom/ns#" term="must have"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="sceduler"/><category scheme="http://www.blogger.com/atom/ns#" term="крон"/><category scheme="http://www.blogger.com/atom/ns#" term="кронтаб"/><category scheme="http://www.blogger.com/atom/ns#" term="планировщик"/><title type='text'>Парсим выражение crontab</title><summary type="text">Crontab - формат файла заданий для планировщика cron. Знаменит простотой, гибкостью и мощью, позволяющими задать практически любую периодичность для выполнения заданий.

Как только выяснилось, что придется писать свой планировщик, мой взгляд сразу обратился на crontab. Но, испугавшись кажущейся сложности его парсинга, я начал придумывать другой, возможно более слабый, но простой в реализации, </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/1319172532298750584/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/12/crontab.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/1319172532298750584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/1319172532298750584'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/12/crontab.html' title='Парсим выражение crontab'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-929311035419767307</id><published>2011-11-23T11:37:00.001+04:00</published><updated>2012-12-26T13:53:36.485+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="audio"/><category scheme="http://www.blogger.com/atom/ns#" term="Phonon"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="аудио"/><category scheme="http://www.blogger.com/atom/ns#" term="воспроизведение"/><category scheme="http://www.blogger.com/atom/ns#" term="звук"/><title type='text'>Phonon: Я хочу, чтобы песня звучала</title><summary type="text">Опыт показывает: пользователь рабочего места, связанного со специфической периферией (автоматизированная касса, испытательный стенд, терминал сбора данных), всегда хочет звукового уведомления о ключевых событиях и нештатных ситуациях. Не миновала чаша сия и меня.

Задача, в общем, тривиальна: хочется, чтобы в определенные моменты программа издавала определенный звук. Какой именно звук, должно </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/929311035419767307/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/11/phonon.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/929311035419767307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/929311035419767307'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/11/phonon.html' title='Phonon: Я хочу, чтобы песня звучала'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-2340463315794296494</id><published>2011-10-28T22:35:00.000+04:00</published><updated>2012-12-26T13:40:58.054+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="math"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="recipes"/><category scheme="http://www.blogger.com/atom/ns#" term="рецепты"/><title type='text'>Рецептики: Проверить дробную часть</title><summary type="text">Проверить, имеет ли число ненулевую дробную часть, можно так:
&amp;gt;&amp;gt;&amp;gt; import math
&amp;gt;&amp;gt;&amp;gt; x = 10.0
&amp;gt;&amp;gt;&amp;gt; bool(math.modf(x)[0])
False
&amp;gt;&amp;gt;&amp;gt; x = 10
&amp;gt;&amp;gt;&amp;gt; bool(math.modf(x)[0])
False
&amp;gt;&amp;gt;&amp;gt; x = 10.7
&amp;gt;&amp;gt;&amp;gt; bool(math.modf(x)[0])
True</summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/2340463315794296494/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/blog-post_3826.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2340463315794296494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2340463315794296494'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/blog-post_3826.html' title='Рецептики: Проверить дробную часть'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-4831224001330468904</id><published>2011-10-28T19:49:00.000+04:00</published><updated>2012-12-26T13:39:50.670+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="recipes"/><category scheme="http://www.blogger.com/atom/ns#" term="рецепты"/><title type='text'>Рецептики: Удалить переводы строки и возвраты каретки</title><summary type="text">Решил для разнообразия иногда публиковать мелкие посты с рецептиками.

Удаление из строки переводов строк и возвратов каретки:
&gt;&gt;&gt; s = &#39;asasd\nasdasd\r\nasdasd\nasdasd&#39;
&gt;&gt;&gt; &#39;&#39;.join(s.splitlines())
&#39;asasdasdasdasdasdasdasd&#39;
</summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/4831224001330468904/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/blog-post_28.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/4831224001330468904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/4831224001330468904'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/blog-post_28.html' title='Рецептики: Удалить переводы строки и возвраты каретки'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-7319460978845916507</id><published>2011-10-28T00:26:00.002+04:00</published><updated>2012-12-27T17:00:54.268+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="NCReport"/><category scheme="http://www.blogger.com/atom/ns#" term="PyNCReport"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="repgen"/><category scheme="http://www.blogger.com/atom/ns#" term="report generator"/><category scheme="http://www.blogger.com/atom/ns#" term="генератор отчетов"/><category scheme="http://www.blogger.com/atom/ns#" term="отчеты"/><category scheme="http://www.blogger.com/atom/ns#" term="сборка"/><title type='text'>PyNCReport: сборка и установка под Windows</title><summary type="text">Всякой уважающей себя учетной программе, даже самой маленькой, требуется подсистема отчетов. Ну любят клиенты бумажные отчеты. Времена, когда подсистемы отчетов писали руками и с нуля каждый под себя, слава высшему разуму, давно прошли. Сегодня разработчик ищет подходящий генератор отчета (далее репген) и прикручивает его к своему творению, чем экономит собственное время, деньги работодателя и </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/7319460978845916507/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/pyncreport-windows.html#comment-form' title='Комментарии: 10'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7319460978845916507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7319460978845916507'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/pyncreport-windows.html' title='PyNCReport: сборка и установка под Windows'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-7542944708924122832</id><published>2011-10-14T00:36:00.000+04:00</published><updated>2012-12-26T13:39:09.236+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model-view"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="внешний ключ"/><category scheme="http://www.blogger.com/atom/ns#" term="модели Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="модель-представление"/><title type='text'>Очистка значений внешних ключей в модели</title><summary type="text">В предыдущем посте я благополучно боролся с отбрасыванием записей, содержащих пустые внешние ключи. Практически сразу возникла в некотором роде обратная задача - уметь очищать поля внешних ключей в модели, как в коде, так и из интерфейса (я встречал мнение, что пустые внешние ключи - грубая ошибка проектирования и этого надо всячески избегать; интересно, в каком мире эти люди живут?). 

Сначала </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/7542944708924122832/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7542944708924122832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7542944708924122832'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/blog-post.html' title='Очистка значений внешних ключей в модели'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-2751280268185620559</id><published>2011-10-07T11:44:00.001+04:00</published><updated>2012-12-26T13:58:38.631+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model-view"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="внешний ключ"/><category scheme="http://www.blogger.com/atom/ns#" term="модели Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="модель-представление"/><title type='text'>Некорректный SQL-запрос SELECT в QSqlRelationalTableModel</title><summary type="text">Было замечено, что в QTableView, настроенном на QRelationalTableModel отображает не все строки таблицы, в частности строки, где значение хотя бы одного поля внешнего ключа (поля, у которых есть QRelation) равно NULL. Более того, оказалось, что эти строки отсутствуют и в модели.

Исследование показало, что QRelationalTableMode.selectStatement возвращает запрос следующего вида: 
SELECT tbl.fld1,
</summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/2751280268185620559/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/sql-select-qsqlrelationaltablemodel.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2751280268185620559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2751280268185620559'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/10/sql-select-qsqlrelationaltablemodel.html' title='Некорректный SQL-запрос SELECT в QSqlRelationalTableModel'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-2483752600804749838</id><published>2011-09-28T00:02:00.000+04:00</published><updated>2012-12-25T18:46:48.053+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GUI"/><category scheme="http://www.blogger.com/atom/ns#" term="MDI"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="интерфейс"/><title type='text'>Тюнинг вкладок QMdiArea</title><summary type="text">Главное окно проекта должно быть многодокументным и в соответствии с современным стандартом де-факто хочется отображать дочерние окна на отдельных вкладках. Для этого в качестве центрального виджета главного окна нужно использовать QMdiArea и установить режим отображения TabbedView

from PyQt4.QtGui import QMainWindow, QMdiArea

class MainWnd(QMainWindow):
    def __init__(self, parent=None):
</summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/2483752600804749838/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/09/qmdiarea.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2483752600804749838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2483752600804749838'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/09/qmdiarea.html' title='Тюнинг вкладок QMdiArea'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_VTNxVCE2X4A8ZFvSoMOEzYUcwTs8OYd_9UyMLD9ap89jwbQIIDEj9o_9gCh7Ldo3JztmI5EGCN-WZV0B3mEDh4j09jEuLWOEdTsRRXRA2pM7hrwZTt5EbbD6uNZmRHkE5g2ElK4JObA/s72-c/firsttabs.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-3097200675826924373</id><published>2011-06-06T22:39:00.008+04:00</published><updated>2012-12-25T18:45:18.360+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="PyWin32"/><title type='text'>Мелкие грабли при работе с PyWin32</title><summary type="text"> Первые грабли
Возникла необходимость написать простую службу Windows. Для этой цели была избрана известная библиотека PyWin32. На просторах интернета было найдено несколько релевантных примеров и быстренько слеплена служба. Тут я напоролся на первую проблему. 

 СимптомыСлужба устанавливается, но не запускается. Функция win32serviceutil.StartService падает с исключением win32service.error со </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/3097200675826924373/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/06/pywin32.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/3097200675826924373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/3097200675826924373'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/06/pywin32.html' title='Мелкие грабли при работе с PyWin32'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-6075113304751359723</id><published>2011-04-02T10:11:00.018+04:00</published><updated>2012-12-25T18:39:54.558+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="automation"/><category scheme="http://www.blogger.com/atom/ns#" term="GUI"/><category scheme="http://www.blogger.com/atom/ns#" term="must have"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="ui"/><category scheme="http://www.blogger.com/atom/ns#" term="unittest"/><category scheme="http://www.blogger.com/atom/ns#" term="интерфейс"/><category scheme="http://www.blogger.com/atom/ns#" term="тестирование"/><title type='text'>Тестирование пользовательского интерфейса в PyQt</title><summary type="text">Мне всегда была интересна тема автоматизации тестирования GUI, ибо задача, мягко скажем нетривиальная. А сейчас возник практический интерес к тестированию UI приложений на PyQT.

Как выяснилось, разработчики впихнули в QT целый фреймворк для автоматического тестирования, который в том числе умеет и эмулировать внешние действия пользователя на интерфейсе. Это называется QtTestLib. Другие </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/6075113304751359723/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2011/04/pyqt.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/6075113304751359723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/6075113304751359723'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2011/04/pyqt.html' title='Тестирование пользовательского интерфейса в PyQt'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhTOwTxL6qPPbQxuFvkdqz23-rPjXIY0ZydG7weslBLcUw3K7tjasCK_WWsynbh7u9ly5eZwTPT_p29cBZVYgbOfOGRv5pwWwiNR7DnJuWlWoOTrm56shgp978rZKr590-BTuZZV0nlhU/s72-c/tcalc1.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-2969121529629556821</id><published>2010-06-09T12:43:00.004+04:00</published><updated>2012-12-25T17:27:26.286+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="must have"/><category scheme="http://www.blogger.com/atom/ns#" term="refactoring"/><category scheme="http://www.blogger.com/atom/ns#" term="дублирование кода"/><category scheme="http://www.blogger.com/atom/ns#" term="инструмент"/><title type='text'>Поиск похожих участков в питоновском коде</title><summary type="text">Когда-то довольно давно отложилось в памяти, что существует полезный инструмент, способный качественно найти в коде на python похожие куски для их дальнейшего рефакторинга.

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



Устанавливается через easy_install 
easy_install -U clonediggerили pip
pip install </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/2969121529629556821/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/06/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2969121529629556821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2969121529629556821'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/06/blog-post.html' title='Поиск похожих участков в питоновском коде'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-7693550285980387925</id><published>2010-05-27T17:43:00.025+04:00</published><updated>2012-12-25T17:24:43.075+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model-view"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="модели Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="модель-представление"/><title type='text'>PyQt: Добавление записей в связанную модель (relationModel) во время редактирования записи основной</title><summary type="text">  Абстрактная задача
Существует таблица main, содержащая помимо прочего поле-ссылку на справочник classifier_id. Код на sqlite:
CREATE TABLE classifier
(
    id INTEGER NOT NULL,
    name TEXT
);

CREATE TABLE main 
(
    id INTEGER NOT NULL,
    name TEXT,
    classifier_id INTEGER REFERENCES classisfier (id)
);
Необходимо написать на PyQt диалог редактирования записи таблицы main с возможностью</summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/7693550285980387925/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/05/pyqt-relationmodel.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7693550285980387925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7693550285980387925'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/05/pyqt-relationmodel.html' title='PyQt: Добавление записей в связанную модель (relationModel) во время редактирования записи основной'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-1624064082328009831</id><published>2010-05-08T03:34:00.009+04:00</published><updated>2011-10-06T15:32:03.581+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="виртуализация"/><category scheme="http://www.blogger.com/atom/ns#" term="инструмент"/><title type='text'>VirtualBox</title><summary type="text">Недавно потребовалось протестировать программку на чистой Windows XP. Дома на машине стоит Windows 7 x64, поэтому пришлось посмотреть в сторону виртуальных машин. На слуху как-то больше VMWare, но мне она почему-то не нравится. Остались от нее какие-то смутные негативные впечатления, когда игрался несколько лет назад.

Кто-то из знакомых в разговоре вскользь упомянул VirtualBox, причем хорошо </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/1624064082328009831/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/05/virtualbox.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/1624064082328009831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/1624064082328009831'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/05/virtualbox.html' title='VirtualBox'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-2651407328420222112</id><published>2010-04-29T02:02:00.010+04:00</published><updated>2012-12-25T16:50:51.988+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="sqlite"/><category scheme="http://www.blogger.com/atom/ns#" term="метаданные"/><title type='text'>Детальные метаданные sqlite3</title><summary type="text">В одном из предыдущих постов я описывал, как получить список таблиц в базе sqlite, и сокрушался, что непонятно, как получить детальную информацию о них. 

Знающие люди ткнули носом в раздел документации sqlite, где описан набор прагм (pragma) для получения исчерпывающей информации о структуре базы. Подробно расписывать не буду, разработчики sqlite прекрасно сделали это сами.

Как выяснилось, эта </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/2651407328420222112/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/sqlite3_29.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2651407328420222112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2651407328420222112'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/sqlite3_29.html' title='Детальные метаданные sqlite3'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-7377027723977687201</id><published>2010-04-29T00:56:00.014+04:00</published><updated>2011-10-13T23:47:24.731+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model-view"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="маппинг виджетов"/><category scheme="http://www.blogger.com/atom/ns#" term="модели Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="модель-представление"/><title type='text'>Нюансы разработки GUI базы данных на PyQt</title><summary type="text">При разработке интерфейса к базе данных на PyQt существует несколько моментов, за которыми нужно следить, чтобы программа вела себя соответственно ожиданиям. Их немного и они, в общем-то, логичны, но с непривычки что-то можно упустить и долго ломать голову, почему нихрена не работает. 

Мне попортили определенное количество крови следующие вещи:


Неотъемлемой частью инициализации </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/7377027723977687201/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/gui-pyqt.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7377027723977687201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/7377027723977687201'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/gui-pyqt.html' title='Нюансы разработки GUI базы данных на PyQt'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-4478577511669927109</id><published>2010-04-24T23:48:00.011+04:00</published><updated>2012-12-25T16:43:58.357+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GUI"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="ui"/><category scheme="http://www.blogger.com/atom/ns#" term="диалог"/><category scheme="http://www.blogger.com/atom/ns#" term="интерфейс"/><title type='text'>PyQt: Генерация кода по ресурсу интерфейса</title><summary type="text">В подавляющем большинстве инструментов для создания GUI, которые мне доводилось использовать, для нормальной работы программы положено из ресурса некоторым образом сгенерировать код. Естественно, полученную рыбу надо наполнить прикладной логикой.

Веселуха начинается, когда возникает необходимость изменить ресурс. Путей при этом два: описания новых контролов ресурса добавлять в ранее </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/4478577511669927109/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/pyqt.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/4478577511669927109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/4478577511669927109'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/pyqt.html' title='PyQt: Генерация кода по ресурсу интерфейса'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-1202148169947550758</id><published>2010-04-24T20:23:00.007+04:00</published><updated>2012-12-25T16:33:27.201+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="sqlite"/><category scheme="http://www.blogger.com/atom/ns#" term="метаданные"/><title type='text'>Метаданные sqlite3</title><summary type="text">Как выяснилось, у sqlite очень просто получить список существующих  таблиц, индексов, представлений и триггеров.


Например, создадим структуру:
CREATE TABLE IF NOT EXISTS table1 (id integer, name text);
CREATE INDEX IF NOT EXISTS index1 ON table1 (name);
CREATE VIEW IF NOT EXISTS view1 AS SELECT name FROM table1;
CREATE TRIGGER IF NOT EXISTS trigger1  DELETE ON table1 
BEGIN 
  select * from </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/1202148169947550758/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/sqlite3.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/1202148169947550758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/1202148169947550758'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/sqlite3.html' title='Метаданные sqlite3'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid92ptQO0fB5Hlt66gOoD7H2woBARWGof7fhl0TNirIb0NOaGAAaw6K9ob9LQrmbNU7qNrvumAVtbVGTZeEatQQ8G4k5-n7ryfc-bvXNSVi29A2AWb8KUuTiq5tL0YKolqB9MFYTAoccw/s72-c/sqlite_master.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6428567201714816130.post-2383123235941104330</id><published>2010-04-24T20:09:00.002+04:00</published><updated>2011-10-13T23:47:40.956+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model-view"/><category scheme="http://www.blogger.com/atom/ns#" term="PyQt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="sqlite"/><category scheme="http://www.blogger.com/atom/ns#" term="модели Qt"/><category scheme="http://www.blogger.com/atom/ns#" term="модель-представление"/><title type='text'>Глюк стандартных SQL-моделей PyQt4</title><summary type="text">При написании простенькой базы данных (PyQt4+sqlite) наткнулся на неприятный глюк связки QSqlTableModel и QTableView: при добавлении во вьюху новых строк активна всегда только первая строка и в базу ничего не пишется.

Выяснилось, что PyQt ни при чем, проблему создавало еще одно соединение с базой средствами стандартного питоновского модуля sqlite3, использовавшееся вспомогательным функционалом. </summary><link rel='replies' type='application/atom+xml' href='http://pythonistaa.blogspot.com/feeds/2383123235941104330/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/sql-pyqt4.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2383123235941104330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6428567201714816130/posts/default/2383123235941104330'/><link rel='alternate' type='text/html' href='http://pythonistaa.blogspot.com/2010/04/sql-pyqt4.html' title='Глюк стандартных SQL-моделей PyQt4'/><author><name>kasatsky</name><uri>http://www.blogger.com/profile/07859278584236303853</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>