Archive for the ‘ironpython’ tag
IronPython talks to Google AppEngine
I’m continuing from my earlier posts on Time Tracking Tool and Authenticating in GAE. When I started with Time Tracking Tool, I had the idea of having a server which will act as a centralized data repository – laptop/desktop tool, mobile tool should send data to the server and data will be analyzed in the server.
To that end, I got the windows desktop client tool talking to a server application. The server is a Google AppEngine Application. Currently there is not much in the server side. Just plain data that is transferred from the client tool. I’ll continue to work on the components and improve on the features – especially dashboard, analytics and similar other features.
To start with download the windows client tool (mySecs_x.x.zip – as the general practice x.x denotes the version) and unzip the content to a directory. You can use the client tool as a standalone tool (without synchronizing data to the server). This is the default configuration. However if you are okay to synchronize then modify the config.xml accordingly.
<serverupdate>0</serverupdate>
<host>mysecs.appspot.com</host>
<email>mysecs@gmail.com</email>
<password>yourpassword</password>
</configuration>
As I said before, client tool works as a stand alone tool by default. If you’re okay to synchronize the data, then change this to 1. I use Google Authentication, hence you need to have a gmail account and provide these in the respective xml nodes.
(A note about data privacy: I don’t pass your email id to the server. So I wouldn’t know about your email id. If you are particular about your email id, which you should be, then create another gmail id for this purpose.
Also, since code for the server is shared, you can download the GAE code and host it on your own).
This is a working version. I’m using it to capture details and synchronize with the GAE server. As I continue to find bugs, I’ll fix them. However if you find bugs, please report them in the Issue Log. (A user reported that it doesn’t work with x64. I don’t know how to fix it. I will search around to fix it).
Next steps? Incorporate with Google Charts to provide some neat analytics reports, so that it really becomes an useful tool.
I need a help though. I am really bad at web design. So if you can take some time of you to design a cool home page and a list page, it will be great. I will surely acknowledge you for your contribution. So if you want to help, please contact me.
Authenticating in GAE
Having successfully created a desktop application in IronPython, I wanted to go a step further – integrate desktop and web environment. Data can be captured in desktop and passed on to web; and analysis can be done on the web.
To start with it, I need to authenticate the incoming request. Hmm…when I started reading about authentication I read so many jargons that scared me – openid, openauth, authsub, basicauth. It took me a while to understand the basics of each (still I don’t claim that I’ve understood them; probably whatever I’ve understood is wrong too)
To some extent, I understood ‘Basic Authentication’ and this is how I went about implementing it.
First of all, I am going with Google Account Authentication, assuming all the users will have a Google account; getting one is not a big deal.
IronPython Desktop Application will pass userid, password to AppEngine Application, which in turn will validate with Google Accounts Authentication service. If authenticated, AppEngine application will proceed; else it will pass the error back to the desktop application.
Having discussed the concepts, here are the code snippets. I’m sharing with a hope that it will be useful to someone; or if this is wrong, someone will raise an alarm; or if there is a better way to do it, someone will comment.
AppEngine
Here the expectation is that the incoming request will have a header (‘HTTP_AUTHORIZATION’) with userid and password in Base64 format.
import urllib
import base64
from google.appengine.api import urlfetch
from django.http import HttpResponse
def authenticate(request):
response_vals={}
resp = HttpResponse()
try:
(method, encoded) = request.META['HTTP_AUTHORIZATION'].split()
response_vals['method'] = method
response_vals['encoded'] = encoded
if method.lower() == 'basic':
(username, password) = base64.b64decode(encoded).split(':')
request_body = urllib.urlencode({'Email': username,
'Passwd': password,
'accountType': 'HOSTED_OR_GOOGLE',
'service': 'ah',
'source': 'test'})
auth_response = urlfetch.fetch('https://www.google.com/accounts/ClientLogin',
method=urlfetch.POST,
headers={'Content-type':'application/x-www-form-urlencoded',
'Content-Length':
str(len(request_body))},
payload=request_body)
resp.status_code = auth_response.status_code
except:
resp.status_code = 401
return resp
return resp
Desktop – Python
Encode the user id, password and call the particular URL (/auth?). And handle the response.
import urllib2
import base64
url = 'http://localhost:8000/api/auth/'
username = 'mysecs@gmail.com'
password = 'mysecspwd'
USER_AGENT = 'mySecsWndClient'
request = urllib2.Request(url)
base64string = base64.encodestring('%s:%s' % (username,password))
authheader = "Basic %s" % base64string
request.add_header('USER_AGENT', USER_AGENT)
request.add_header('AUTHORIZATION', authheader)
try:
response = urllib2.urlopen(request).read()
print response
except urllib2.HTTPError, e:
print e.code
print e.read()
except urllib2.URLError, e:
if hasattr(e, 'reason'):
print e.reason
elif hasattr(e,'code'):
print e.code
Desktop – IronPython
Since I’ve written mySecs in IronPython, I’ve to translate the above into IronPython. As ipy is a relatively new entrant, there is not much of documentation on how to do it. Here is what I’ve done.
from System.IO import StreamReader
from System.Net import HttpWebRequest, NetworkCredential, WebException
url = 'http://localhost:8000/api/auth/'
username = 'mysecs@gmail.com'
password = 'mysecspwd'
USER_AGENT = 'mySecsWndClient'
req = HttpWebRequest.Create(url)
req.UserAgent = USER_AGENT
auth_string = '%s:%s' % (username,password)
authheader = "Basic %s" % System.Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(auth_string))
req.Headers.Add('AUTHORIZATION', authheader)
try:
rsp = req.GetResponse()
response = StreamReader(rsp.GetResponseStream()).ReadToEnd()
print response
rsp.Close()
except (Exception, WebException), e:
print 'Error: %s' % e
Applies to: GAE 1.1.1; Django 0.96 with helper; IronPython 1.1
Reference:
AuthSub Authentication for Web Applications
IronPython Learnings
Recently I started developing Windows Desktop Applications in IronPython – a Python language port for Windows.NET. I blogged about the application already here.
In the post, I’m sharing what I learnt in the process with a hope that it will be helpful to someone else.
Visual Studio as ipy development environment
You can download IronPython and start to develop using your favorite text editor. However having a Visual Studio environment helps. Fundamentally it involves:
- Download and install ironpython
- Download and install Visual Studio SDK
- Run IronPython Integration Sample from ‘C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Samples\IronPythonIntegration’
Designing Windows Forms
With Visual Studio Integration, designing of Windows Forms is a simple drag and drop operation. Of course code generated by VS may not be as elegant as some Python purists like; but it works well.
Calling unmanaged code from IronPython
If you are into IronPython, you’ll definitely come across VoidSpace, who has a huge collection of IronPython articles.
I needed to query the active window for my application. VoidSpace discusses a solution in his pages. Better to name the namespace as a ‘UnmanagedCode’ as VoidSpace discusses in the solution. I named it as the name of the application and that created a lot of trouble and was difficult to troubleshoot.
Logging in IronPython
IPY doesn’t include standard python libraries (at least as of 1.1). So I used a NSpring .NET logging library.
(I found out that any .NET library can be used with IronPython. I did same with SQLite Library and SourceGrid, a grid library for .NET)
Finding time difference
One can find the time difference between two time variable (=System.DateTime.Now) using
timeSpent = currentEndTime.Subtract(currentStartTime)
If you want to know the differences in seconds then use
timeSpentinSec = timeSpent.TotalSeconds.ToString()
timeSpent.Seconds() will provide only the seconds part of the timespan. TotalSeconds() provide the time difference in seconds.
Don’t forget to stop timer
I used Timer() to poll activewindow on a regular interval. However, I forgot to stop that assuming that once the form is closed all instances will be cleared. Apparently not and so the application stayed in memory even after exit. Lesson learnt: stop all threads before exiting the application.
A time tracking tool
While I was waiting for Django 1.0 to be released, I wanted to quickly learn to develop desktop applications. I preferred it to be on Python so that I can continue to learn the language. I did an evaluation of different options and settled on IronPython.
As a consultant, there is always a need to submit timesheets. By the end of the day/week, it is difficult to remember the tasks done during that time-span (day/week). If somehow a tool can capture applications that were worked on, then it will help.
So I developed an application for the same.
This application polls the active window at an interval of 5 seconds and captures the application details (application name and the application title) and the time spent on each of these tasks.
It can be minimized into systray so that it can continue to capture details without any disturbance (first icon).
One can download the details on the grid as a csv file too.
Currently thats all in there. As I continue to use (and probably get some feedback) I will continue to enhance it.
The project is hosted in Google. One can download the executable and the source.