IdeaMonk

thoughts, ideas, code and other things...

Monday, June 28, 2010

Yet another Google Calculator shell in Python

For the sake of weekend hack and getting rid of some headache of post bangpypers meetup chicken overload of today's evening -
import re
import urllib
import mechanize
import unittest

class GCalc:
def __init__(self):
self.browser = mechanize.Browser()
self.browser.set_handle_robots(False)
self.browser.addheaders = \
[('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

def cleanup(self,text):
strip_tags = re.compile("<.*?>")
return strip_tags.sub('', text.replace("<sup>","^").replace("</sup>","").replace("×","X"))

def calc(self, query):
try:
raw_result = self.browser.open("http://www.google.com/search?hl=en&q="+urllib.quote_plus(query)).read()
return self.parse(raw_result)
except:
return "Failed to reach Google"

def parse(self, raw_result):
try:
result = raw_result.split('''<td style="vertical-align:top" >''')[1].split('</h2>')[0] + '</h2>'
return self.cleanup(result)
except:
return "Not a calculator query"

class TestGCalc(unittest.TestCase):
def setUp(self):
self.g = GCalc()

def test_numeric(self):
self.assertEqual(self.g.calc("4+5"), "4 + 5 = 9")

def test_bignumbers(self):
self.assertEqual(self.g.calc("234623476 * 59999999999"), "234 623 476 * 59 999 999 999 = 1.40774086 X 10^19")

def test_units(self):
self.assertEqual(self.g.calc("14 inch in mm"), "14 inch = 355.6 millimeters")
self.assertEqual(self.g.calc("one acre"), "one acre = 4\xc2\xa0046.85642 m^2")

def test_cacl(self):
self.assertEqual(self.g.calc("3 * PI / sin(3)"), "(3 * PI) / sin(3) = 66.7855543")

def test_facts(self):
self.assertEqual(self.g.calc("speed of light"), "the speed of light = 299\xc2\xa0792\xc2\xa0458 m / s")


if __name__=='__main__':
unittest.main()

Fork it here, have fun, curse me for crappy splits :)
Just learnt unittest a bit, ah so easy and useful :D

I guess you can notice the grand theme here - Its just ~ 50 lines of code packed up with a unit test and does the job!

I suggest you better not miss PyCon India 2010 in case you too are eager to do some productivity magic with you/your employees/students/etc.

Adios

Labels: ,

16 Comments:

At June 29, 2010 12:52 PM , OpenID zubin71 said...

unittest rocks; but for the above code snippet, using doctests makes would have made more sense, i think.

 
At June 29, 2010 1:01 PM , OpenID zubin71 said...

btw, see ya at pycon! ;)

 
At June 29, 2010 1:02 PM , Blogger Abhishek Mishra said...

I came across doctests while working on a bulk uploader for pykata, they're using it in a very interesting way to create self testing problem formats

Though I could write a parser for their format but doctest was still looked like magic to me. Would look into it later as have been pointed to this by multiple people.

After all this is a very lame hackish code with lot of magic strings inside, once things change on google's side, even a minor formatting, it would fail.

 
At June 29, 2010 4:19 PM , OpenID zubin71 said...

I think you are confusing docstrings and doctests.
docstrings are of course, for documentation, while doctests _are_ exclusively for testing.
usually they are put in the same modules but you can also have them in seperate text files.

 
At June 29, 2010 4:29 PM , Blogger Abhishek Mishra said...

"confusing docstrings and doctests" - seriously wouldn't that be kinda extra lame.

Well the problem format in pykata has a doctest attached to it, so that it can be easily tested before submission by a problem setter. Which is what I was pointing out as my first encounter with doctests, in case you failed to see the import or doctest.testmod

 
At June 29, 2010 6:21 PM , Anonymous l0nwlf said...

@ideamonk : zubin is right. He have 3 year experience with python and is a profound and elegant software-developer and you are just a kid. So STFU and listen to what he says.

 
At June 29, 2010 8:49 PM , OpenID zubin71 said...

@ideamonk I am sorry but I dont see your point when you said
"they're using it in a very interesting way"

I did notice the doctest import at the bottom; but thats just how doctests are always used. I don't see whats particularly interesting about that.

`n yeah, guess 'docstring-doctest' would be kinda xtra-lame; so sorry about that :)

 
At June 29, 2010 9:07 PM , OpenID zubin71 said...

@l0nwlf "but i still need someone to teach me OOPs concepts. fast!"

hey! wait.. where have i heard that before?

oh! that was you! :D

 
At June 29, 2010 9:17 PM , Blogger Abhishek Mishra said...

Heh interestingly the problem description is packed in the docstrings, the solution and testing code is present as functions. But then that would interest the people in context.

So again I stand corrected as I was never confusing docstrings and doctest as you point out, isn't it?

 
At June 29, 2010 9:20 PM , OpenID zubin71 said...

No, i stand corrected as you were never wrong in the first place :D

 
At June 29, 2010 9:21 PM , Blogger Abhishek Mishra said...

Normally people would keep problem descriptions etc in a database, and keep the correction logic elsewhere, what David and Andrew have done here is to pack a problem description and its logic into a single executable, testable for its own correctness, portable entity, allowing easy import exports :)

But then one would understand all this when one reads the page properly before making a lame comment.

 
At June 29, 2010 9:29 PM , Anonymous l0nwlf said...

@zubin71 Exactly. That why I said Ideamonk to STFU and listen to you. Of course you are much more experienced python programmer than both of us and what you commented must have been True.

PS. I still need to learn OOP concepts :(

 
At June 29, 2010 9:32 PM , OpenID zubin71 said...

I repeat. I stand corrected. :)

 
At June 29, 2010 9:33 PM , OpenID zubin71 said...

@l0nwlf want me to teach you? like with mercurial? :P

 
At June 29, 2010 9:39 PM , Anonymous l0nwlf said...

@zubin71 Sure, if you know enough. I guess I can benefit from your experience in python and DVCS. Volunteer help is always welcome, one of the many benefits of OSS.

 
At June 29, 2010 10:00 PM , OpenID zubin71 said...

@l0nwlf Yup! Nothing quite like the spirit of OSS and learning ain't it? :)

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home