Уведомления

Группа в Telegram: @pythonsu

Уведомления

  • Found 3495 posts.

Флейм » Вакансия - требуется программист Python (Санкт-Петербург) » Июнь 4, 2012 11:58:21

Обязанности:

Проектирование базы данных, написание программного кода в соответствии с техническим заданием.


Требования:

Профессиональное знание Python;
Опыт работы с одним или несколькими веб фреймворками (Django, TurboGears, Flask, Pyramid, etc.);
Знание SQL (Mysql, Postgres);
Опыт проектирования баз данных с нуля;
Знание JavaScript, AJAX, HTML/HTML5, CSS;
Способность осмысленно подходить к выбору используемых технологий;


Ваши преимущества:

Возможность показать несколько примеров кода;
Участие в open source проекте;
Уверенное знание ОС GNU/Linux;

Тип занятости
Полная занятость, полный день

Заработная плата по результатам собеседования.

Телефон: +7 (812) 929-07-60 Сергей

Центр помощи » Протокол CGI » Июнь 1, 2012 20:01:54

Нужна помощь с курсовым проектом, на сайт html&css создать таблицу в одном из подразделов сайта. И возможность её менять онлайн. Сделать это через протокол cgi на python. Кто может пишите, vk свой дам или icq чтобы поподробней объяснить. (будет вознаграждение).

Web » Не получается ввод данных в форму на сайте » Май 31, 2012 08:58:44

Вот задачка, помогите решить, у меня пока никак не получается

Есть
http://fx-trend.com/pamm/rating/

Если в ручную ввести в поле “Кол-во периодов” - 1 и нажать кнопку “Применить”, то в графе “Максимальная просадка” будут нужные цифры (они отличаются от получаемых по умолчанию ) и я хочу получить это с помощью python.

Пока у меня ни как не получается это сделать - чтобы я не посылал в post - приходит страница без нужных мне параметров. Также не получается авторизоваться на этом сайте по https - что нужно для получения некоторых дополнительных данных.
Большое спасибо всем кто откликнется и поможет решить вопрос с кодом для этого конкретного примера.

Django » django cms + bootstrap » Май 29, 2012 20:13:35

Здравствуйте!

Решил попробовать что такое django cms и заодно оценить все прелести bootstrap интерфейса.

В процессе разработки появилась следующая идея/задача: сделать набор шаблонов для WYSIWYG редактора, что бы менеджер сайта используя нужный шаблон и поменяв в нем текст/заглушку мог вставить новый блок на страницу. А идея в том, что бы использовать эти шаблоны в последующем при создании сайтов с bootstrap интерфейсом.

С чем то подобным приходилось сталкиваться, тогда я реализовал это следующим образом: Использовал в качестве WYSIWYG редактора TinyMCE. В TinyMCE редакторе есть такая функция “Insert Predefined Template Content”, она позволяет вставлять html шаблон из html файла.
пример шаблона:
<div class="container">
  <h1>Введите заголовок</h1>
  <div class="author">Автор материала</div>
  <div class="text">Текст материала</div>
</div>

В django cms по умолчанию используется в качесвте WYSIWYG редактора WYMeditor. WYMeditor мне очень понравился, и отказываться от него в пользу TinyMCE желания не возникло. Но вот если с TinyMCE я имел достаточно долгий опыт работы, то с WYMeditor познакомился совсем недавно. К сожалению функции аналогичной “Insert Predefined Template Content” в редакторе WYMeditor я пока не смог найти (наверное плохо искал).

Собственно вопрос: как вы думаете, как правильно решить такую задачу, через добавление в WYSIWYG редактор готовых шаблонов, или же есть еще какое то решение?
Что вы по всему этому думаете?

Спасибо за внимание.

Python для новичков » Хостинг Pyramid проекта  » Май 29, 2012 00:43:58

Подскажите хостинг с поддержкой Pyramid и MongoDB

Центр помощи » параллельное умножение матриц с помощью очередей » Май 26, 2012 20:28:47

ОЧЕНЬ НУЖНО!Помогите пожалуйста реализовать параллельное умножение матриц , нужно брать из очереди строку из1оймитр и столбец из 2ой умножать и засовывать в выходную очередь. Нужно доделать код


Флейм » Прошивка на питоне для Telit (Python on Telit GL865) » Май 24, 2012 17:26:08

Необходимо написать прошивку для GSM модуля Telit GL865 для целей мониторинга транспорта. К модулю по RS 232 подключен GPS модуль.
В базовой прошивке необходимо:
1. Реализация отправки строки а ля NMEA по TCP-IP по расписанию (задается частота съема информации в движении и на стоянке). В строке указывается показания датчиков.
2. Поддержка команд на конфигурирование.
3. Обновление прошивки по GPRS.

Оплата по этапам. ТЗ на первый этап высылается после получения мною информации о ваших аналогичных проектах.

Просьба не слыть предложения без реального опыта написания Питон прошивок для модулей Telit.
Контакт Максим Роньшин +380505067999 blaze собакатакая digsee точкатакая com

Центр помощи » Задача о восьми ферзях » Май 21, 2012 18:50:52

Всем привет!
Этот код находит кол-во всех возможных расположений N-ферзей на доске NxN.Wikipedia.
Используеться backtracking+рекурсия.
Мог бы ктонибудь переделать этот рекурсивный алгоритм в нерекурсивный использущий стэк(stack).

from array import array

solution_count = 0

def queen(current_row, num_row, solution_list):
if current_row == num_row:
global solution_count
solution_count = solution_count + 1
else:
current_row += 1
next_moves = gen_nextpos(current_row, solution_list, num_row + 1)
if next_moves:
for move in next_moves:
solution_list[current_row] = move
queen(current_row, num_row, solution_list)
solution_list[current_row] = 0
else:
return None

def gen_nextpos(a_row, solution_list, arr_size):
cand_moves = []
for column in range(1, arr_size):
under_attack = False
for row in range(1, a_row):
if (abs(a_row - row) == abs(column - solution_list[row])
or solution_list[row] == column):
under_attack = True
break
if not under_attack:
cand_moves.append(column)
return cand_moves

def main():
size=input('Ukazite razmeri stola:')
solution_list = array('i', [0]* (size + 1))
queen(0, size, solution_list)
print("Kol-vo vozmoznix raspolozenij: "+str(solution_count))


main()

Python для экспертов » celery и запуск задач последовательно » Май 21, 2012 14:41:56

Здравствуйте

Использую для выполнения долгих задач celery. Столкнулся с такой задачей. Имеется Task, который принимает какие-то параметры на входе и делает что-то. Есть 1 параметр, например IP, который может быть одинаков для разных задач. Требуется сделать очередь из задач с одинаковыми IP. Т.е., если нету запущеной задачи с этим IP, то запустить, иначе поставить в очередь и ждать заверешения задачи с таким IP, при этом задачи с отличным IP должны работать параллельно и запускаться.

Как такое реализовать, не совсем понимаю. Думал делать динамически очереди по IP, но как ограничить тогда количество воркеров для очереди?

Mobile Python » Узнать номер исходящего звонка, pys60 » Май 21, 2012 12:02:09

Приветствую. Такая проблема: необходимо при осуществлении вызова узнать непосредственно сам набранный номер, telephone выдает пустую строку, т.е. не подходит, есть еще способы?

Zope/Plone/Bluebream » есть ли в природе руководство на русском языке по Dexterity? » Май 20, 2012 17:07:30

Может кто в курсе, есть ли хоть какое-то, пусть даже самое краткое руководство на РУССКОМ языке по использованию Dexterity? И вообще есть ли большая разница между Dexterity и Archetypes?(сори за нубский вопрос) Очень нужна любая информация.

Флейм » Ищу квалифицированных специалистов. » Май 17, 2012 20:39:16

Друзья, я ищу программистов на python и архитекторов баз данных. Вся информация в документе по ссылке. Прошу обратить внимание на то, что зарплаты указаны ОТ.
https://docs.google.com/document/d/1abOT0asGjew_fW6atTWcg9GbhR57YWr10oBdu4HdyRM/edit

Флейм » Админка базы данных » Май 17, 2012 12:33:41

Добрый день всем! Очень интересует есть ли проекты (отдельные или в рамках CMS), позволяющие администрировать базу данных наподобие админки django?

Python для новичков » Грамматики простого и слабого предшествования  » Май 17, 2012 10:45:34


По каждой КС-грамматике G можно построить таблицу
предшествования T (точнее говоря, T(G)). Строки и столбцы таблицы
однозначно поименованы основными и вспомогательными символами грамматики
и дополнительным символом #.
В клетки T(x,y) таблицы помещаются символы <,=,> по следующим
правилам (в которых u и v могут быть произвольными строками):
1) T(x,y) содержит <, если G содержит правило вида A->uxBv такое,
что существует непустой вывод строки, начинающейся с y, из символа B.
2) T(x,y) содержит >, если y - основной символ, и G содержит правило
вида A->uBZv такое, что существуют непустой вывод строки, кончающейся
на x, из символа B и (возможно, пустой) вывод строки, начинающейся
с y, из символа Z (когда упомянутый последним вывод пуст, Z совпадает
с y).
3) T(x,y) содержит =, если G содержит правило вида A->uxyv.
4) T(#,y) содержит <, если в G из аксиомы можно вывести
строку, начинающуюся с y.
5) T(x,#) содержит >, если в G из аксиомы можно вывести
строку, кончающуюся на x.

Если T(x,y) содержит <, > или =, будем употреблять также
обозначения x<y, x>y, x=y, соответственно (заметим, что одно-
временно может быть x<y, x>y и x=y).

G называется грамматикой простого предшествования, если
каждое из множеств T(x,y) содержит не более одного элемента.
G называется грамматикой слабого предшествования, если
1) каждое из множеств T(x,y) одновременно ссимволом > не может
содержать ни символа <, ни символа =, 2) если G содержит два
правила A->uXv и B->v, то не может быть ни X<B, ни X=B.

Следующая грамматика для арифметических выражений типа a+a*(a*a+a)
является обратимой грамматикой слабого (но не простого) предшествования.

E->E+T | T
T->T*F | F
F->(E) | a

Ниже приводится таблица предшествования для этой грамматики

| E T F a ( ) + * #
__|___________________________
E | = =
T | > > = >
F | > > > >
a | > > > >
) | > > > >
( |<= < < < <
+ | <= < < <
* | = < <
# | < < < < <

Алгоритм анализа.

Ниже будем считать, что G - обратимая (т.е. не содержит
разных правил с одинаковой правой частью) и приведенная
(т.е. не содержит выводов вида A->B->…->A, и удовлетворяет
некоторым другим простым условиям, которые обычно выполняются
для естественным образом построенных грамматик).

Пусть s - входная строка, дополненная в конце символом #,
и m - вспомогательная строка (стек), вначале равная #.
На каждом шаге работы имеется указатель на некоторый символ строки
s (в начале работы указывается первый символ s) и указатель
на последний символ стека m.

Алгоритм состоит из этапов переноса и свертки.
Пусть x - последний символ стека m, y - очередной символ во
входной строке s.
1) Если x<y или x=y, то y переносится в m, и указатель на
s переносится на следующий символ.
2) Если x>y, то в хвосте m производится свертка (т.е. замена
правой части некоторого правила на его левую часть), если это
возможно. Для грамматик простого предшествования такое правило
(если оно есть) определяется однозначно. Для грамматик слабого
предшествования это может быть не так: в этом случае надо
заменять самую длинную правую часть. Если такого правила нельзя
найти, то s нельзя вывести в G;
3) Если T(x,y) пусто, то s нельзя вывести в G (кроме случая
x=E,y=#, в этом случае надо выйти из цикла и проверить стек
на равенство с #E как ниже).

Если таким образом удается обработать всю строку s и в конце
работы m равен #E, где E - аксиома грамматики G, то делается
вывод, что s можно вывести в G, а в противном случае -
s не выводится в G.





Всем здравствуйте! Ладно, я сразу признаюсь, что я чайник. У меня есть небольшие знания - однако же, их хватило на то, чтобы выполнить первые две лабораторные, да и то с помощью. Эту программу я просто-напросто не понимаю. Не прошу просто сделать ее за меня и прислать, что вы. Но я бы очень попросила хотя бы совет, как начать, а то я в ступоре. Спасибо.

Python для экспертов » Правильное пакетирование » Май 14, 2012 21:30:04

Есть некий пакет, скажем foo, с вот такой структурой:
foo/
__init__.py
mod1.py
mod1.py
common/
__init__.py
commonmod1.py
commontmod2.py
plugin1/
__init__.py
plugin1mod1.py
plugin2mod2.py
plugin2/
__init__.py
plugin2mod1.py
plugin2mod2.py
Хочется написать правильный setup.py, который позволит сделать прямое соответствие питоновый пакет(python egg) -> deb/rpm пакет. То есть из этой структуры хочется получить три пакета - foo-common, foo-plugin1 и foo-plugin2. Проблема в том, что все это добро лежит в одном дереве. Если я указываю в setup.py
packages = ['foo']
, то в foo.egg попадает и plugin1/*.py и plugin2/*.py. Подскажите как это вообще сделать, не меняя дерево исходников.

Центр помощи » Подскажите пожалуйста код программы для получения ESSID доступных вай фай сетей с помощью dbus » Май 11, 2012 16:32:17

Добрый день. Питон для меня язык новый (абсолютно новый).
Кто-то мог бы выложить пример программы для получения списка ESSID вай фай сетей с помощью dbus?
Ковыряюсь уже 2-й день и не могу понять, то ли у меня линукс неверно настроен, то ли шина dbus барахлит. По примерам на оф сайте написал код ниже, но он не работает, выбивает ошибку:
Method getProperties with signature “” on interface “org.freedesk…” does not exist.

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

#!/usr/bin/python
import dbus
NM_DBUS_SERVICE = "org.freedesktop.NetworkManager.Devices.wlan0"
NM_DBUS_OBJECT_PATH = "/org/freedesktop/NetworkManager/Devices/wlan0"
NM_DBUS_INTERFACE = NM_DBUS_SERVICE
def get_wlan_networks():
        bus = dbus.SystemBus()
        wlan = bus.get_object(NM_DBUS_SERVICE, NM_DBUS_OBJECT_PATH)
        wlan_dev_intf = dbus.Interface(wlan, dbus_interface=NM_DBUS_INTERFACE)
        props = wlan_dev_intf.getProperties()
        return props
print get_wlan_networks()

GUI » Выделенный текст » Май 10, 2012 21:21:55

Как получить выделенный в произвольном приложение текст на винде?

Python для новичков » Усредняющий фильтр 31х31. » Май 7, 2012 18:28:15

При обработке изображения необходимо применить усредняющий фильтр размером 31х31.
Думал воспользоваться PIL, но там ограничение на фильтр 5х5.
то есть максимум что я его заставил сделать:
class AVG5(BuiltinFilter):
    name = "AVG5"
    filterargs = (5, 5), 25, 0, (
        1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,
        1,  1,  1,  1,  1
        )
а нужно:
class AVG31(BuiltinFilter):
    name = "AVG31"
    filterargs = (31, 31), 961, 0, (
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
        )
Может есть не большая библиотека способная на это?
Сейчас делаю это попиксельно в цикле, но это невыносимо долго, может есть способ ускорить?

GUI » Как попроще научить Tkinter.Text показывать невидимые символы? » Май 7, 2012 13:29:29

Как попроще научить Tkinter.Text показывать невидимые символы?
Например символ перевода строки.

Network » Вебсокет(WebSocket) - сообщения не передаются » Май 7, 2012 12:41:52

Всем добрый день. Пытаюсь сделать простой эхо websocket-сервер. За основу взял этот код. Однако он работает со старым протоколом-76. Начал переделывать под протокол 07, соединение проходит успешно, однако сообщения не передаются. Искал в чем может быть причина, но так и не нашел. Я новичек в питоне, поэтому решил спросить у вас: что я сделал не так? Заранее благодарен. Код привожу ниже:

import time
import struct
import socket
import hashlib
import sys
from select import select
import re
import logging
from threading import Thread
import signal
from base64 import b64encode
class WebSocket(object):
    handshake = (
	"HTTP/1.1 101 Switching Protocols\r\n"
	"Upgrade: websocket\r\n"
	"Connection: Upgrade\r\n"
	"Sec-WebSocket-Accept: %(accept)s\r\n"
	"Sec-WebSocket-Protocol: chat\r\n"
	"\r\n"
    )
    def __init__(self, client, server):
        self.client = client
        self.server = server
        self.handshaken = False
        self.header = ""
        self.data = ""
    def feed(self, data):
        if not self.handshaken:
            self.header += data
            if self.header.find('\r\n\r\n') != -1:
                parts = self.header.split('\r\n\r\n', 1)
                self.header = parts[0]
                if self.dohandshake(self.header, parts[1]):
                    logging.info("Handshake successful")
                    self.handshaken = True
        else:
            self.data += data
            msgs = self.data.split('\xff')
            self.data = msgs.pop()
            for msg in msgs:
                if msg[0] == '\x00':
                    self.onmessage(msg[1:])
    def dohandshake(self, header, key=None):
        logging.debug("Begin handshake: %s" % header)
        for line in header.split('\r\n')[1:]:
            name, value = line.split(': ', 1)
            if name.lower() == "sec-websocket-key":
                key_accept = value+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
            	key_accept = hashlib.sha1(key_accept).digest()
		key_accept = b64encode(key_accept)
            	handshake = WebSocket.handshake % {
                	'accept': key_accept
            	}
        else:
            logging.warning("Not using challenge + response")
            handshake = WebSocket.handshake % {
                'accept': key_accept
            }
        logging.debug("Sending handshake %s" % handshake)
        self.client.send(handshake)
        return True
    def onmessage(self, data):
        logging.info("Got message: %s" % data)
    def send(self, data):
        logging.info("Sent message: %s" % data)
        self.client.send("\x00%s\xff" % data)
    def close(self):
        self.client.close()
class WebSocketServer(object):
    def __init__(self, bind, port, cls):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind((bind, port))
        self.bind = bind
        self.port = port
        self.cls = cls
        self.connections = {}
        self.listeners = [self.socket]
    def listen(self, backlog=5):
        self.socket.listen(backlog)
        logging.info("Listening on %s" % self.port)
        self.running = True
        while self.running:
            rList, wList, xList = select(self.listeners, [], self.listeners, 1)
            for ready in rList:
                if ready == self.socket:
                    logging.debug("New client connection")
                    client, address = self.socket.accept()
                    fileno = client.fileno()
                    self.listeners.append(fileno)
                    self.connections[fileno] = self.cls(client, self)
                else:
                    logging.debug("Client ready for reading %s" % ready)
                    client = self.connections[ready].client
                    data = client.recv(1024)
                    fileno = client.fileno()
                    if data:
                        self.connections[fileno].feed(data)
                    else:
                        logging.debug("Closing client %s" % ready)
                        self.connections[fileno].close()
                        del self.connections[fileno]
                        self.listeners.remove(ready)
            for failed in xList:
                if failed == self.socket:
                    logging.error("Socket broke")
                    for fileno, conn in self.connections:
                        conn.close()
                    self.running = False
if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
    server = WebSocketServer("localhost", 9999, WebSocket)
    server_thread = Thread(target=server.listen, args=[5])
    server_thread.start()
    # Add SIGINT handler for killing the threads
    def signal_handler(signal, frame):
        logging.info("Caught Ctrl+C, shutting down...")
        server.running = False
        sys.exit()
    signal.signal(signal.SIGINT, signal_handler)
    while True:
        time.sleep(100)