REPL WebPart для SharePoint
Опубликовано: 24 октября, 2009 Filed under: .net, C#, DLR, Python, sharepoint, tdd | Tags: DLR, IronPython, Isolator, sharepoint, TypeMock 1 комментарийIntro
Сегодня я расскажу о прототипе первого компонента под ярлычком Sapphire. Это REPL WebPart. Эта веб-часть предназначенная для производства оперативных изменений на серверной стороне SharePoint, так же для удаленного исполнения скриптов и тестирования некоторых кусков кода.
PreBody
Производство данной веб-части было инициированно в довольно таки частых потребностях исполнения серверного кода с достаточной оперативностью, в недоступности средств разработки под рукой.
Здесь есть небольшая презетнация, в которой я постарался отобразить принципы работы Repl WebPart:
В добавок к слайдам расскажу о том, что веб-часть представляет собой классический хостинг Dynamic Languages Runtime языков, пока из которых доступен только Python.
Body
Далее хотелось поговорить о том, как же всё это у меня получилось, итак проект включает в себе несколько основных модулей:
- Веб-часть и контролы представления
- Хостинг языков
Далее о них поподробнее
Language Hosting
В связи с тем, что языков, которые я захочу реализовать в данном проекте является неограниченное множество, то конечно же мне необходима абстрактная фабрика для их создания, которая будет скрывать иерархию всех доступных языков и инкапсулировать их под интерфейсом:
{
ILanguage Create(string name);
}
public interface ILanguage
{
string Name { get; }
object Execute(string input);
void SetVar(string name, object value);
object GetVar(string name);
}
Отлично, далее к нашему проекту присоединяются сборки, необходимые для имплементации скриптовых языков:
- IronPython.dll
- Microsoft.Dynamic.dll
- Microsoft.Scripting.Core.dll
- Microsoft.Scripting.ExtensionAttribute.dll
- Microsoft.Scripting.dll
Всё готово для того, чтобы реализовать Python, как среду для исполнения кода, отлично, приступим:
{
private readonly ScriptScope _scope;
public string Name
{
get { return «Python»; }
}
public PythonLanguage()
{
_scope = Python.CreateEngine().CreateScope();
}
public object Execute(string input)
{
ScriptSource source = _scope.Engine.CreateScriptSourceFromString(input);
return source.Execute(_scope);
}
}
Далее немного усложним задачу, в связи с тем, что нам будет необходимо реализовать контекст для работы с SharePoint, выглядеть это должно примерно так:
private void python_should_assume_sharepoint_variables()
{
SPWeb fakeWeb = Isolate.Fake.Instance<SPWeb>();
Isolate.WhenCalled(() => fakeWeb.Title).WillReturn(«I’m fake web»);
var python = _factory.Create(«Python»);
python.SetVar(«__x__», «123»);
python.SetVar(«__web__», fakeWeb);
python.Execute(«__x__ = __web__.Title»);
var x = (string)python.GetVar(«__x__»);
Assert.AreEqual(x, «I’m fake web»);
}
Для работы с объектами SharePoint в из IronPython, нам необходимо добавить несколько библиотек:
_scope.Engine.Runtime.LoadAssembly(typeof(Uri).Assembly);
_scope.Engine.Runtime.LoadAssembly(typeof(SPList).Assembly);
Это будет основой нашей работы с динамическими языками
WebPart + WebControls
Создадим проект с помощью SPVisualDev, добавим в него feature, внутри которой создадим веб-часть Repl WebPart, всё остальные действия стандартные, однако есть небольшой нюанс, нам нужен будет объект, с помощью которого можно будет выводить строковые значения после исполнения. Я решил создать для этих целей объект с классическим названием Console, его реализация предельна проста:
{
private readonly StringBuilder _messageBuilder = new StringBuilder();
public void Write(object message)
{
_messageBuilder.Append(message);
}
public void WriteLine(object message)
{
_messageBuilder.AppendLine(message.ToString());
}
public string Message
{
get
{
return _messageBuilder.ToString();
}
}
}
Мы будем передавать его в среду исполнения языков, а после исполнения кода опрашивать его свойство Message и выводить его содержимое в нашу веб-часть.
EndBody
Все исходники проекта доступны на github: http://github.com/butaji/Sapphire
Так же предварительную версию Sapphire.Environment (решение поставляется в WSP) можно слить на CodePlex: http://sapphire.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34895
Habrahabr, Live Writer и Code Highlighting
Опубликовано: 17 октября, 2009 Filed under: .net, Blog, Live, Python | Tags: IronPython, Live Writer, Pygments 1 комментарийИнтро
Уже практически полгода я пользуюсь Windows Live Writer в качестве инструмента для написания веб-ориентированных статей. Это отличный инструмент, работающий с большим количеством blogengine’ов, и даже с SharePoint. Но разговор не об этом, в связи с тем, что я разработчик, мне частенько приходится вставлять листинг кода в написанные статьи, на это я и хочу обратить ваше внимание.
Пигменты
Многие представители Python-сообщества наверняка знакомы с дивным проектом под названием Pygments:
Ну так вот, товарищ Harry Pierson (@DevHawk) скомпилировал этот движок под IronPython и написал обертку-плагин для Windows Live Writer (качать здесь не торопиться). Отлично, однако то, что получается в результате его обработки не выделяется цветом на habrahabr, это связанно с некоторыми особенностями ресурса, однако поправимо.
Данными работами я и предлагаю заняться, для этого нам понадобятся:
- Исходники проекта (на GitHub’е)
- 5 мин времени
После того, как мы скачали исходники, стоит разыскать скрипт под именем pygments_package\devhawk_formatter.py и немного его подкоректировать:
# colors are readily specified in hex: ’RRGGBB’
if style[‘color’]:
start += ‘<span style=»color:#%s«>’ % style[‘color’]
end = ‘</span>’ + end
заменить на
# colors are readily specified in hex: ’RRGGBB’
if style[‘color’]:
start += ‘<font color=»#%s«>’ % style[‘color’]
end = ‘</font>’ + end
Далее пересобрать с помощью скрипта build.bat проект и запустить инсталлер – теперь то что делает данный проект в цвете отображается на хабре.
Как забыть про ярлыки на рабочем столе?
Опубликовано: 7 сентября, 2009 Filed under: Productive, Python | Tags: Enso, Humanized, launcher, Productive, Python 3 комментарияВведение
Раньше у меня довольно часто возникала проблема захламления рабочего стола огромным количеством ярлыков, и я начинал теряться в них, соответственно терять время при поиске необходимых мне приложений. В дальнейшем я научился пользоваться сочетанием клавиш win+r, создавая ярлыки с короткими именами в system32. С приходом Windows Vista (7) теперь только кнопки win, однако гибкость и настройка данных методов весьма ограниченна. Имеется так же огромное количество hotkey-менеджеров, однако не с одним из них я так и не сдружился.
Лаунчеры
Недавно (по-моему после прочтения книги «Продуктивный программист. Как сделать сложное простым, а невозможное – возможным» Нила Форда) мой интерес пал на launcher’ы. Для windows-платформы я нашёл несколько:
- SlickRun http://www.bayden.com/SlickRun/
- slimCODE http://www.slimcode.com/
- Colibri http://colibri.leetspeak.org/ – некоторый аналог небезызвестного Quicksilver для Mac OS X
- Launchy http://www.launchy.net/
Ну и герой этого поста:
Немного истории
Изложу настолько, насколько я сумел разобраться в ней. Первоначально Enso был строго коммерческим проектом, разрабатываемым компанией Humanized (основанной Джеффри Раскиным, в котрой в последующем работал его сын). В дальнейшем компания начала работу над Mozilla Ubiquity (аналог Enso, являющийся плагином для FireFox), что позволило ей сделать Enso бесплатным.
Enso
Лучше 1 раз увидеть, чем 7 раз прочитать, базовые возможности представлены в следующих роликах:
На настоящий момент на сайте компании есть две версии продукта:
- Версия 1 http://humanized.com/enso/
удобна в эксплуатации, но умеет делать лишь базовые вещи.
настройка (как и во второй версии) происходит через embeded веб-сервер
- Версия 2 http://humanized.com/enso/beta/all/ (остальное на данной странице является плагинами для Enso)
в данной версии появилось огромное количество очень полезных плагинов (к примеру поиск в google, генерация объектов-карт по выделенному адресу) однако юзабили немного упало (с моей точки зрения) в плане того, что после ввода команды начала открываться отдельная строка для ввода параметров, на что уходило время, и приходилось нажимать лишний раз enter
Все отлично, за исключением того, что проект на данном сайте вроде как заброшен, что не совсем воодушевляло к использованию, однако слазив внутрь и посмотрев реализацию, обнаружилось, что всё написано на Python (межплатформенность?), а так же исходники доступны в свободном доступе, что немного приободрило.
В дальнейших поисках упоминаний о Enso я наткнулся на коммунити http://www.ensowiki.com, а так же (самое главное) хостинг нынешей версии Enso https://launchpad.net/enso, итак, что же изменилось с тех времен:
- настройка больше не через веб-сервер
- межплатформенность (Windows, Linux, Mac OS X, etc)
- интерфейс первой версии
- практически все плагины из второй версии
Используем Enso
Для установки существует инсталлер, поэтому трудности вряд ли могут встретиться. Далее у меня возникла необходимость в настройке (теперь для совершения настроек существует файл enso\config.py) “основной” клавиши (Caps Lock) в режим залипания (Sticky в терминологии создателей программы), для этого я проделал следующее:
IS_QUASIMODE_MODAL = True
Расширяем Enso
Классно, мой питомец (Enso) теперь стал послушным и ласковым, однако хочется научить его понимать новые команды, ну что ж, пускай это будет Enso hello world.
Я отправился в папку commands в корне, куда добавил файл butaji.py со следующим содержимым:
from enso.messages import displayMessage
def cmd_butaji(ensoapi, cmd):
if cmd == «time»:
ensoapi.display_message(«Hello world»)
cmd_butaji.valid_args = [‘time’]
И у меня получилось следующее:
Великолепно! я думаю, что мы с Enso очень сдружимся.
Анализ рынка ноутбуков с помощью Python
Опубликовано: 31 августа, 2009 Filed under: DataMining, Notebook, Price, Python | Tags: DataMining, Ноутбук, Цены, Notebook, Price, Python Оставьте комментарийВведение
В этой статье я расскажу о состоянии на сегодняшнем российском рынке ноутбуков. Всю аналитику мы будем проводить с помощью кода на python. Думаю она будет полезна как тем, кто ищет ноутбук, так и тем, кто хочет потренироваться написанию на python.
Начнём
Для анализа нам необходим набор данных, к сожалению я не смог обнаружить веб-сервисы у российских он-лайн магазинов ноутбуков, поэтому мне пришлось скачать прайс-лист одного из них (я не стану называть его) и вытащить из него цены и основные параметры (по-моему мнению таковыми являются: частота процессора, диагональ монитора, объем оперативной памяти, размер жесткого диска и объем памяти на видео-карточке). Далее я провёл некоторый анализ по следующим вопросам:
- Средняя стоимость ноутбука
- Усредненные параметры железа на ноутбуках
- Самая дорогая/дешевая конфигурация ноутбука
- Какой из параметров конфигурации больше всего влияет на его цену
- Прогнозирование цены указанной конфигурации
- График распределения конфигураций и цен
Lets code
Прайс-лист, который мне удалось заполучить я сохранил в формате CVS, для работы с ним необходимо подключить модуль cvs:
import re
import random
Так же подключим модуль для работы со случайными числами и регулярными выражениями, которые в последствии нам понадобятся.
Далее создадим метод для чтения и получения ноутбуков:
reader = csv.reader(open(‘data.csv’), delimiter=‘;’, quotechar=‘|’)
return filter(lambda x: x != None, map(create_notebook, reader))
здесь всё просто, мы читаем на файл с данными data.csv и фильтруем по результату функции create_notebook, т.к. не все позиции в прайсе являются ноутбуками, а вот кстати и она:
try:
notebook = Notebook()
notebook.vendor = raw[0].split(‘ ’)[0]
notebook.model = raw[0].split(‘ ’)[1]
notebook.cpu = getFloat(r»(\d+)\,(\d+)\s\Г», raw[0].split(‘/’)[0])
notebook.monitor = getFloat(r»(\d+)\.(\d+)\»», raw[0].split(‘/’)[1])
notebook.ram = getInt(r»(\d+)\Mb», raw[0].split(‘/’)[2])
notebook.hdd = getInt(r»(\d+)Gb», raw[0].split(‘/’)[3])
notebook.video = getInt(r»(\d+)Mb», raw[0].split(‘/’)[4])
notebook.price = getInt(r»(\d+)\s\руб.», raw[1])
return notebook
except Exception, e:
return None
Как вы можете заметить, я решил не обращать внимания на вендора, модель и тип процессора (здесь конечно не всё так просто, но тем не менее), а и ещё — в данном методе присутствуют мои кастомные функции-помощники:
m = re.search(regex, raw).groups()
return float(m[0] + ‘.’ + m[1])
def getInt(regex, raw):
m = re.search(regex, raw).groups()
return int(m[0])
Хочу заметить, что писать для питона лучше всего в стиле наборов данных, а не ООП структур, в связи с тем, что язык больше располагает к такому стилю, однако для наведения некоторого порядка в нашей доменной области (ноутбуки), я ввёл класс, как вы могли заметить выше (notebook = Notebook())
pass
Отлично, теперь у нас есть структура в памяти и она готова для анализа (2005 различных конфигураций и их стоимость), что же начнём:
Средняя стоимость ноутбука:
print sum([n.price for n in get_notebooks()])/len(get_notebooks())
Исполняем код и видим, что 1K$, как стандарт для компьютера всё ещё в силе:
34574
Усредненные параметры железа на ноутбуках
print «cpu {0}».format(sum([n.cpu for n in get_notebooks()])/len(get_notebooks()))
print «monitor {0}».format(sum([n.monitor for n in get_notebooks()])/len(get_notebooks()))
print «ram {0}».format(sum([n.ram for n in get_notebooks()])/len(get_notebooks()))
print «hdd {0}».format(sum([n.hdd for n in get_notebooks()])/len(get_notebooks()))
print «video {0}».format(sum([n.video for n in get_notebooks()])/len(get_notebooks()))
Та-да, и в наших руках усредненная конфигурация:
cpu 2.0460798005
monitor 14.6333167082
ram 2448
hdd 243
video 289
Самая дорогая/дешевая конфигурация ноутбука:
Функции идентичны, за исключением функций min/max
maxprice = max([n.price for n in get_notebooks()])
maxconfig = filter(lambda x: x.price == maxprice, get_notebooks())[0]
print «cpu {0}».format(maxconfig.cpu)
print «monitor {0}».format(maxconfig.monitor)
print «ram {0}».format(maxconfig.ram)
print «hdd {0}».format(maxconfig.hdd)
print «video {0}».format(maxconfig.video)
print «price {0}».format(maxconfig.price)
cpu 2.26
monitor 18.4
ram 4096
hdd 500
video 1024
price 181660
cpu 1.6
monitor 8.9
ram 512
hdd 8
video 128
price 8090
Какой из параметров конфигурации больше всего влияет на его цену
Очень интересно было бы узнать, за какой из параметров конфигурации мы платим больше всего денег. Прикинув, я предположил, что скорее всего это диагональ монитора и частота процессора, ну что же, думаю, что стоит проверить это.
Для начала наш набор параметров конфигурации стоит немного модифицировать. В связи с тем, что единицы измерения различных параметров различны в своём порядке, нам необходимо привести их к одному знаменателю, т.е. нормализовать их. Итак, приступим:
notebooks = get_notebooks()
cpu = max([n.cpu for n in notebooks])
monitor = max([n.monitor for n in notebooks])
ram = max([n.ram for n in notebooks])
hdd = max([n.hdd for n in notebooks])
video = max([n.video for n in notebooks])
rows = map(lambda n : [n.cpu/cpu, n.monitor/monitor, float(n.ram)/ram, float(n.hdd)/hdd, float(n.video)/video, n.price], notebooks)
return rows
В данной функции я нахожу максимальные значения для каждого из параметров, после этого формирую результирующий список ноутбуков, в котором каждый из параметров представлен в виде коэффициента (его значение будет колебаться от 0 до 1), показывающего отношение его параметра к максимальному значению в наборе, к примеру память в 2048Mb даст конфигурации коэффициент в ram = 0.5 (2048/4056).
Вклад каждого из параметров мы будем считать в рублях, для наглядности, хранить эти веса мы будет в наборе:
koes = [0, 0, 0, 0, 0]
Я предлагаю исчислять эти коэффициенты для каждой конфигурации, а после этого определить среднюю величину всех коэффициентов, что даст нам усредненные данные о весе каждого из элементов конфигурации.
koeshistory = []
#наши ноутбуки
notes = normalized_set_of_notebooks()
for i in range(len(notes)):
koes = [0, 0, 0, 0, 0]
#устанавливаем коэффициенты
set_koes(notes[i], koes)
#сохраняем историю коэффициентов
koeshistory.extend(koes)
#показываем прогресс выполнения
if (i % 100 == 0):
print i
print koes
Как же мы будет устанавливать коэффициенты для каждого элемента конфигурации? Мой способ заключается в следующем:
- нам необходимо в случайном порядке наращивать, либо уменьшать значение одного из коэффициентов
- после чего анализировать, приблизились ли мы к цене за конфигурацию, при умножении вектора параметров на вектор коэффициентов (напомню, что в нашем случае это рубли)
- если приближение состоялось, ты мы повторяем данное действие, если же нет, то отменяем его
- повторять данный порядок до той степени, пока не приблизимся к нашей цене с установленной нами точностью
Вот реализация данного алгоритма:
price = get_price(note, koes)
lasterror = abs(note[5] — price)
while (lasterror > error):
k = random.randint(0,4)
#изменяем коэффицинт
inc = (random.random()*2 — 1) * (error*(1 — error/lasterror))
koes[k] += inc
#не даём коэффициенту стать меньше нуля
if (koes[k] < 0): koes[k] = 0
#получаем цену при учёте коэффициентов
price = get_price(note, koes)
#получаем текущую ошибку
curerror = abs(note[5] — price)
#проверяем, приблизились ли мы к цене, казанной в прайсе
if (lasterror < curerror):
koes[k] -= inc
else:
lasterror = curerror
inc – переменная отвечающая за цвеличение/уменьшение коэффициента, способ её вычисления объесняется тем, что данное значение должно быть тем больше, чем больше разница в ошибке, для быстрого и более точного приближения к желаемому результату.
Умножение векторов для получения цены выглядит следующим образом:
return sum([note[i]*koes[i] for i in range(5)])
Пришла пора выполнить анализ:
cpu, monitor, ram, hdd, video
[15455.60675667684, 20980.560483811361, 12782.535270304281, 17819.904629585861, 14677.889529808042]
Данный набор мы получили, благодаря усреднению коэффициентов, полученных для каждой из конфигураций:
koes = [0, 0, 0, 0, 0]
for row in koeshistory:
for i in range(5):
koes[i] += koeshistory[i]
for i in range(5):
koes[i] /= len(koeshistory)
return koes
Итак, у нас получился желаемый набор, что же мы можем сказать из этих цифр, а можем мы составить рейтинг параметров:
- Диагональ монитора
- Объем жесткого диска
- Частота процессора
- Объем видео-карточки
- Объем оперативной памяти
Хотелось бы отметить, что это далеко не идеальный вариант, и у вас могут получится иные результаты, однако, моё предположение, о том, что частота процессора и диагональ дисплея наиболее важные параметры в конфигурации, частично подтвердились.
Прогнозирование цены указанной конфигурации
Классно бы было, имея такой богатый набор данных, уметь прогнозировать цену на заданную конфигурацию. Этим мы и займемся.
Для начала преобразуем нашу коллекцию ноутбуков в список:
return map(lambda n: [n.cpu, n.monitor, n.ram, n.hdd, n.video, n.price], get_notebooks())
Далее нам понадобиться функция, способная определить расстояние между двумя векторами, хорошим вариантом я вижу функцию эвклидова расстояния:
d = 0.0
for i in range(len(v1)):
d+=(v1[i] — v2[i])**2;
return math.sqrt(d)
Корень из суммы квадратов разностей довольно таки наглядно и эффективно показывает нам насколько один вектор различен от другого. Чем же полезна для нас данная функция? Всё просто, когда мы получим вектор, с интересующими нас параметрами, мы пробежимся по всей коллекции нашего набора и найдём ближайшего соседа, а его стоимость мы уже знаем, отлично! Вот как мы это сделаем:
distancelist=[]
for i in range(len(data)):
vec2 = data[i]
distancelist.append((euclidean(vec1,vec2),i))
distancelist.sort()
return distancelist
Далее, можно немного усложнить задачу, а так же точность предоставляемых данных. Для этого мы введем функцию, использующую классификацию методом k взвешенных ближайших соседей:
взвешенных ближайших соседей — это метрический алгоритм классификации, основанный на оценивании сходства объектов. Классифицируемый объект относится к тому классу, которому принадлежат ближайшие к нему объекты обучающей выборки.
Ну и взять среднее значение среди некоторого количества ближайших соседей, что сведет на нет влияние цен вендора, либо специфичности конфигурации:
dlist = getdistances(data, vec1)
avg = 0.0
for i in range(k):
idx = dlist[i][1]
avg +=data[idx][5]
avg /= k
return avg
*последние 3 алгоритма взяты из книги Сегерана Тоби “Программируем коллективный разум”
И что же мы получаем:
31521.0
>> knnestimate(get_notebooks_list(), [2.0, 15, 2048, 160, 256])
27259.0
>> knnestimate(get_notebooks_list(), [2.0, 15, 2048, 160, 128])
20848.0
Цены рыночные и этого вполне достаточно, хотя мы абсолютно не учитываем в этой реализации, к примеру частоту процессора и диагональ монитора (для этого нам необходимо добавить в функцию сравнения векторов их веса , которые мы вычисляли в предыдущем пункте)
График распределения конфигураций и цен
Хочется объять картину распределения целиком, т.е. нарисовать распределение конфигураций и цен на рынке. Ок, сделаем это.
Для начала надо поставить библиотеку matplotlib. Далее подключить её к нашему проекту:
Так же нам понадобится создать два набора данных, для оси абсцисс и ординат:
return map(lambda x: x[0]*x[1]*x[2]*x[3]*x[4], normalized_set_of_notebooks())
def config_prices():
return map(lambda x: x[5], normalized_set_of_notebooks())
И функцию, в которой мы построим график распределения:
plot(config_prices(),power_of_notebooks_config(),‘bo’, linewidth=1.0)
xlabel(‘price (Rub)’)
ylabel(‘config_power’)
title(‘Russian Notebooks Market’)
grid(True)
show()
И что же мы получаем:
В завершение
Итак, у нас получилось провести небольшой анализ российского рынка ноутбуков, а так же немного проиграться с python.
Исходный код проекта доступен по адресу:
http://code.google.com/p/runm/source/checkout
Ruby|Python в браузере, сделай сам
Опубликовано: 1 августа, 2009 Filed under: DLR, javascript, Python, Ruby, silverlight | Tags: ClientSide, DLR, Gestalt, javascript, Python, Ruby, silverlight Оставьте комментарийЗачем?
Клиентскую часть в веб-приложениях принято создавать на JavaScript. Я считаю, что большинство разработчиков с огромным удовольствием бы отошли от этого правила и воспользовались своим любимым server-side языком. Ну что же, команда MIX Online предоставила любителям динамических языков такую возможность, подробнее об этом можно прочитать в “Проект Gestalt – пишите на Ruby, Python и XAML прямо в HTML на стороне клиента”. Ниже я предлагаю создать нечто подобное, но уже своими силами.
С помощью чего?
Посмотрев несколько примеров мне стало ясно, что реализован Gestalt на Silverlight + Dynamic Languages Runtime. Далее я прикинул, а на сколько сложно создать нечто своими руками? И сразу же решение: Silverlight умеет взаимодействовать с DOM – значит я смогу получить код и интерпритировать его – дело за малым – реализация.
Приступим
Нам понадобятся:
- Visual Studio >2008SP1 (при желании можно и другие IDE или средства редактирования текста)
- Silverlight >2.0 Tools
- Dynamic Languages SDK >0.5.0 (download)
- 10 мин времени
Lets code
Открываем Visual Studio, создаём Silverlight Application, я назову проект “mygestalt”. Теперь я осознаю, что писать та надо будет совсем не много, мне понадобится экспериментальный Client-Script и его интерпритатор. Открываем страничку, на которой будет хоститься наш Silverlight, в моём случаем это mygestaltTestPage.aspx и добавляем туда наш client-side python code. Выглядеть это должно примерно так:
- <script type="python">
- def func():
- HtmlPage.Window.Alert("Hello world!")
- func()
- </script>
* This source code was highlighted with Source Code Highlighter.
Далее отправляемся в MainPage.xaml.cs, где будем заниматься поисками нашего скрипта:
- using System.Linq;
- using System.Windows.Browser;
- namespace mygestalt
- {
- public partial class MainPage
- {
- public MainPage()
- {
- InitializeComponent();
- FindAndRunScript();
- }
- private void FindAndRunScript()
- {
- var scripts = HtmlPage.Document.GetElementsByTagName("script");
- var pythonScript = scripts.Where(x => x.GetProperty("type").ToString() == "python").First();
- PythonEngine.Run(pythonScript.GetProperty("innerHtml").ToString());
- }
- }
- }
* This source code was highlighted with Source Code Highlighter.
Ну и реализация PythonEngine:
- using Microsoft.Scripting;
- using Microsoft.Scripting.Hosting;
- using Microsoft.Scripting.Silverlight;
- namespace mygestalt
- {
- public static class PythonEngine
- {
- public static ScriptScope Run(string source)
- {
- var setup = Configuration.LoadFromAssemblies(Package.GetManifestAssemblies());
- setup.HostType = typeof(BrowserScriptHost);
- setup.DebugMode = true;
- var runtime = new ScriptRuntime(setup);
- var engine = runtime.GetEngine("IronPython");
- var scope = engine.CreateScope();
- const string init = @"
- import clr
- clr.AddReference('System.Windows.Browser')
- from System.Windows.Browser import *
- "
;
- ScriptSource initSource = engine.CreateScriptSourceFromString(init, SourceCodeKind.Statements);
- initSource.Execute(scope);
- var script = engine.CreateScriptSourceFromString(source, SourceCodeKind.Statements);
- script.Execute(scope);
- return scope;
- }
- }
- }
* This source code was highlighted with Source Code Highlighter.
Запускаем приложение и видим:
В заключение
Вот у нас и получился свой собственный Gestalt, самое интересное в том, что я посмотрел его исходники и нашёл там примерно такую же реализацию.
Мой проект можно найти на http://code.google.com/p/mygestalt/.
Всем спасибо!
Звучит заманчиво: Django на IronPython
Опубликовано: 29 марта, 2009 Filed under: asp.net, DLR, iis, iis6, iis7, Python | Tags: .net, asp.net, Django, IronPython, NWSGI, Python, WSGI 5 комментариевdef Introduce():
Дорогие мальчики и девочки, меня (как позже оказалось не только меня) интересует веб-индустрия и всё, что с ней связано, соответственно хочется вкусить разнообразных технологий, одной из них является известный фреймворк Django. Им и хочется заняться. Думаю, не стоит говорить, о том, что я .NET-разработчик, в связи с чем Python в чистом виде использовать не очень хочется, но хочется попробовать IronPython в деле. Тогда вполне очевидно, что Django на .NET должен являться ASP.NET приложением.
def WSGI():
Здесь нам нужно знать, что такое WSGI:
WSGI (англ. Web Server Gateway Interface, произносится виски) — стандарт взаимодействия между Python-программой, выполняющейся на стороне сервера, обычно из каталога cgi-bin, и самим веб-сервером, например, Apache.
Дополнительная информация: PEP 333
И нам безусловно повезло, т.к. есть готовая имплементация WSGI для ASP.NET: NWSGI – выполнена как ASP.NET 2.0 HttpHandler на IronPython.
Что примечательно, мало того, что NWSGI интегрируется с IIS и позволяет работать с сессиями, кешем и управлением пользователями, он интегрируется даже с графической средой управления IIS 7!
Это ещё не всё, NWGSI умеет также работать с Cassini (веб-сервер Visual Studio).
Думаю Вам, ровно как и мне, не терпится поработать с этим.
def PrepareIIS():
Итак, что нам необходимо:
- IronPython 2.0
- NWSGI 1.0
- Огромное желание сделать что-нибудь особенное на этом.
Для установки из пакета NWSGI копируем пример HelloWorld в папку C:\inetpub\wwwroot\HelloWorld (либо другой путь для ваших IIS приложений). Из этого же пакета копируем NWSGI.dll в папочку HelloWorld\bin (если пользовались инсталлятором, то в этом нет необходимости, т.к. она уже в GAC’е).
Далее из пакета IronPython 2.0 копируем в каталог HelloWorld\bin следующие сборки:
- IronPython.dll
- IronPython.Modules.dll
- Microsoft.Scripting.Core.dll
- Microsoft.Scripting.dll
Наша папочка HelloWorld должна выглядеть следующим образом:
HelloWorld\
- bin\
- NWSGI.dll (optional)
- IronPython.dll
- IronPYthon.Modules.dll
- Microsoft.Scripting.Core.dll
- Microsoft.Scripting.dll
- hello.wsgi
- Web.Classic.config
- Web.Integrated.config
Далее, если у нас ISS 7.0, то тогда копируем Web.Integrated.config в Web.config, иначе Web.Classic.config в Web.config.
Далее добавляем приложение на IIS, это можно сделать, как через графическое меню, так и воспользоваться консолью:
%systemroot%\system32\inetsrv\appcmd add app /site.name:"Default Web Site" /path:/hello /physicalPath:C:\inetpub\wwwroot\HelloWorld
Если же у вас IIS 6, то путь один – через графическое меню, а так же необходимо будет ассоциировать *.wsgi с ASP.NET ISAPI фильтром (по аналогии с *.aspx)
Теперь идём по адресу http://localhost/hello/hello.wsgi. И видим грациозное: "Hello, World!", yeah!
def InstallDjango():
Установить Django можно с помощью команды:
ipy setup.py install
Далее можно добавить проект и сгенерировать приложения:
ipy manage.py startapp AppName
ipy manage.py startproject ProjName
К сожалению, мне не хватило навыков для того, чтобы запустить django-приложение под NWSGI.
def SqlServer():
Подключить Django к Microsft SQL Server 2005 и выше можно с помощью следующей библиотеки:
http://code.google.com/p/django-mssql/
Так же можно почитать о подключении здесь: http://blogs.msdn.com/dinoviehland/archive/2008/03/17/ironpython-ms-sql-and-pep-249.aspx
def GetGratitude():
Огромную благодарность за выполненную работу хочу выразить Jeff Hardy и советую ознакомиться с его работами:
Codeplex: Очередной Add-In для Reflector’а
Опубликовано: 21 января, 2009 Filed under: Boo, DLR, Python | Tags: codeplex, IronPython, reflector Оставьте комментарийСегодня на Codeplex нашёл плагин, который позволяет рефлектору интерпритировать сборки в IronPython. Довольно таки интересно.
На рисунке интерпретирована сборка Boo в IronPython.
Ссылка на релиз http://www.codeplex.com/ipreflector.
Что такое ALT.NET?
Опубликовано: 21 января, 2009 Filed under: .net, agile, ALT.NET, architecture, asp.net, Boo, C#, coding, DLR, DSL, Microsoft, Microsoft.NET, Python, Ruby | Tags: ALT.NET 1 комментарийВведение
По многочисленным WTF от коллег, хотел бы вкратце прояснить, а что же это такое. А дальше решайте сами, интересно Вам это или нет.
Содержание
ALT.NET — Альтернативные инструменты и подходы к разработке на .NET.
Инструменты и подходы перечислены ниже в табличке HOTorNOT.
Hot | Not |
Castle, ActiveRecord, NHibernate |
DataSets, Dataset Designer, Entity Framework, MS Application Blocks |
MVC,NUnit,MonoRail | Web Forms, SCSF, VSTS, MSTest |
XP, TDD, Scrum | MSF Agile, MSF For CMMI |
Evolutionary Design and Development | Big Design Up Front |
Ruby + IronRuby, Python + IronPyton, DLR, Silverlight(?) | ? |
OR\M (NHibernate, LLBLGen etc..) | DLinq, Data Access Block, DataSets, Plain ADO. NET |
Open Source (Mono, SourceForge) | Application Blocks, CodePlex |
MVC and MVP (RoR, MonoRail..) | Web Forms, CAB, Smart Client Factory |
CVS, SVN | VSS, VSTS Source Control |
Build Automation and CI (CI Factory, NAnt, FinalBuilder, CruiseControl..) |
Team Build |
TDD and Unit Testing NUnit, MbUnit, RhinoMocks, NMock, TypeMock |
MSTest for unit testing, VSTS |
Subtext, DasBlog, WordPress, TypePad, Blogger, FeedBurner | Microsoft MSN Spaces, Community Server(?) |
Simplicity in Design | P&P |
Working at Google | Working at MS |
Google Gears | Smart Client, MS Ajax |
.NET 3.X (WF, WPF. Silverlight) | .NET 2.0 |
DI, IoC, Spring for .NET | Object Builder |
Conferences: OSCon, RubyCon, Code Camps, DevTeach.. |
VSLive, TechEd, DevConnections.. |
Считаю, что необходимо как минимум ознакомиться со всеми перечисленными понятиями как в правой, так и в левой колонках, следуя принципу анализ-синтез-best practices.
Материалы по теме
- Табличка любезно позаимствована здесь http://weblogs.asp.net/rosherove/archive/2007/06/04/alt-net-alternative-tools-and-approaches-to-mainstream-net.aspx
- Страница сообщества ALT.NET http://altdotnet.org/
- Статья в журнале MSDN “Что такое ALT .NET?” by Джереми Д. Миллер (Jeremy D. Miller) http://msdn.microsoft.com/ru-ru/magazine/cc337902.aspx
- Активно развивающаяся группа ALT.NET на Yahoo Groups http://tech.groups.yahoo.com/group/altdotnet/
Обзор языка Boo! – как средства организации DSL Вашего приложения
Опубликовано: 28 декабря, 2008 Filed under: .net, architecture, Boo, C#, coding, DLR, DSL, Microsoft.NET, Python, Ruby, visual studio | Tags: .net, Boo, DSL, Python Оставьте комментарийОдна из вещей, как известно, способная помочь вам стать лучше в качестве разработчика, заключается в изучении нового языка. Даже если Вы никогда не будете пользоваться этим языком в Вашей повседневной трудовой деятельности, он поможет Вам лучше понять языки, с которыми Вы работаете.
В последнее время меня так и тянет насесть на какой-нибудь новенький язык программирования, особенно что-нибудь на типа Ruby или Python, но в связи с моей привязанностью среде разработки (Visual Studio, неверно это не очень хорошо – зависеть от IDE ;)) и затруднительной ситуацией с разработкой на ней на динамических языках (надеюсь это временное затруднение) от них пока пришлось отказаться. В то же время меня интересуют такие области как метапрограммирование и реализация DSL (Domain-Specific Language == проблемно-ориентированный язык приложения), и в этой связи видится мне, что Boo является весьма интересным языком. К тому же Boo — язык CLR, что очень даже не плохо для изучения.
Поэтому я решил, что когда я узнаю Boo и когда почувствую уверенность в Boo, я попробую реализовать DSL и реализовать именно на Boo для своего ближайшего проекта.
Что такое Boo?
Boo представляет собой open-source объектно-ориентированный статически типизированный язык программирования для CLR с Python’о-подобным синтаксисом, язык увидел свет в 2004 году из-под рук Rodrigo B. de Oliveira. В настоящее время последняя версия 0.8.2, но даже если нет еще версии 1.0, это действительно очень стабильной и зрелый язык, который можно использовать на производстве.
Основные концепции в Boo:
- Дать компилятору сделать большую часть работы, для того чтобы помочь языку выглядеть более динамическим с автоматическим объявлением переменных, выводом и приведением типов.
- В то же время он предоставляет возможности для выполнения статической компиляции, проверку ошибок во время компиляции.
- Boo также предоставляет функциональную составляющую в том, что функции могут использоваться в качестве возвращаемого значения, как аргументы, хранимые в переменных, а так же как объекты.
- Boo имеет первоклассные генераторы, это конструкций, способные производить более одного значения при использовании итерации цикла (“return a for a in apples if a.IsRipe”).
- Boo также поддерживает утиную типизацию (Duck Typing), которая позволяет отказаться от обеспечения безопасности статических типов и принимать любой объект, который просто имеет соответствующие методы и свойства, определяемые во время выполнения.
- Boo также имеет расширения методов и свойств (extension methods and extension properties).
Одним из наиболее интересных функций Boo является расширяемость процесса компиляции, которая позволяет управлять компиляцией и изменять или добавлять функции. Можно добавить подпрограмм для проверки конвенции кода, генерирования отчётов или преобразовывания кода. То, что Вы сможете сделать в C# с помощью тулзы посткомпиляции такой, как PostSharp и только ограниченный набор действий. В Boo Вы могли бы например автоматически преобразовать класс в одноэкземплярный (pattern Singleton), просто добавив атрибут следующим образом:
[singleton]
class MySingleton: pass
PostSharp просто не смог бы сделать этого, свойство экземпляра было бы обработано поздно. Это действительно открывает множество возможностей и Вы ограничиваетесь только Вашим пониманием внутренней функциональности компилятора и набора его возможностей.
В Boo пробелы имеют важное значение как в python, но есть возможность включить режим “Whitespace Agnostic”, позволяющий оканчивать выражение с помощью “end”, который избавит Вас от возможных проблем с пробелами.
Что нужно для начала работы с Boo?
Главным образом если Вы хотите узнать Boo, достаточно иметь последнюю версию Boo . В папке bin, Вы найдете файл “Booish.exe”, являющийся интерпретатором командной строки Boo, которая позволяет проиграться с синтаксисом языка.
Для разработки нам необходима IDE, и следовательно у нас два варианта.
Большинство Boo разработчиков работают с SharpDevelop , и если Вы скачаете последнюю версию, в ней будет Boo полностью готовый к использованию. Эта IDE имеет преимущество, с точки зрения создания DSL, так как в ней легче добавить функции автозавершения кода и подсветки синтаксиса, в Visual Studio же потребуются написать лексер и парсер; в SharpDevelop можно сделать это с помощью XML-файла.
Но с другой стороны Visual Studio является зрелой IDE, и с BooLangStudio вы получите Boo интегрированный в Visual Studio. Люди жалуются, что проект является нестабильным и это лишь альфа выпуск, так же я встретился в нём с проблемами уникода (UTF8), которые пока не смог разрешить, но у меня пока нет весомых замечаний.
В настоящее время я буду пользоваться Visual Studio в силу привычки, но я могу изменить свой взгляд при продолжении этой статьи.
При написании данного поста я руководствовался данной работой, можно даже сказать переводил, но перевод очень личный и свободный.
Продолжение следует…