RSS Icon

Topics

View Comments

Convert a string to an integer in Python

Topics: interview python

A fun interview question some developers like to ask is to have you convert ascii characters to an integer without using built in methods like string.atoi or int().

So using python the obvious ways to convert a string to an integer are these:

>>> int('1234')
1234
>>> import string
>>> string.atoi('1234')
1234

The interesting thing here is finding out where on the ascii character table the number is. Luckily python has this already built in with the ord method:

>>> help(ord)

ord(...)
    ord(c) -> integer
    
    Return the integer ordinal of a one-character string.

>>> ord('1')
49
>>> ord('2')
50

You can see that the numbers are grouped together on the ascii table, so you just have to grab '0' as the base and subtract the rest:

>>> ord('1')-ord('0')
1

So if we have the string '1234', we can get each of the individual numbers by looping over it:

>>> num_string = '1234'
>>> num_list = []
>>> base = ord('0')
>>> for num in num_string:
...   num_list.append(ord(num) - base)
... 
>>> print num_list
[1, 2, 3, 4]
but now how to we combine all these together to get 1234? You can't just add them up because you'll just get 1+2+3+4 = 10.

So, we have to get 1000 + 200 + 30 + 4, which is a simple problem to solve. Its just number times 10 to the nth power, so the final solution is:

num = '1234'
new_num = 0 
base = ord('0')

for i,n in enumerate(reversed(num)):
      new_num += (ord(n) - base) * (10**i)

print new_num

This code is a little verbose though, lets make it a dirty nasty one liner!

>>> sum([(ord(n)-ord('0')) * (10 ** i) for i,n in enumerate(reversed('1234'))])
1234

View Comments

Debugging Python with pdb

Topics: pdb python

Being a great debugger is almost as important as being great at writing the software. I think I spend just as much time debugging programs as I do writing them. pdb (python debugger) is a very powerful tool for interactively debugging the state of your application and inspecting portions of your code.

For the rest of this post we are going to be debugging a file called fib.py with the following code:

# fib.py
def main():
    low = 0
    high = 1
    for i in range(10):
        print high
        new_high = get_new_high(low, high)
        low = high
        high = new_high 

def get_new_high(low, high):
    return low + high

if __name__ == '__main__':
    main()

There are many ways to get your application to drop into pdb, the first way is to import pdb in the file you want to debug and put pdb.set_trace() on any lines you want to debug. So we are going to change our file to look like this:

def main():
    import pdb;pdb.set_trace()
    low = 0
    high = 1
    for i in range(10):
        print high
        new_high = get_new_high(low, high)
        low = high
        high = new_high 

def get_new_high(low, high):
    return low + high

if __name__ == '__main__':
    main()

You will see it shows you what method its in and the next line its going to run:

python fib.py
> /home/sontek/code/test/fib.py(3)main()
-> low = 0

The second way is to tell the python interpreter to break as soon as it starts your application using the -m argument:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
</module>

You can see it stopped at the very first line in my application and then from there I can inspect arguments, jump to lines of code, and set break points.

To get some extra context while you are debugging a useful command is the 'list' command:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) list
  1  ->	def main():
  2  	    low = 0
  3  	    high = 1
  4  	    for i in range(10):
  5  	        print high
  6  	        new_high = get_new_high(low, high)
  7  	        low = high
  8  	        high = new_high 
  9  	
 10  	def get_new_high(low, high):
 11  	    return low + high
</module>

You will notice the '->' character combination will show you where you currently are and list will by default show you 11 lines of code. You can also give it a range of line numbers to display by passing it first and last line arguments like this:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) list 1,4
  1  ->	def main():
  2  	    low = 0
  3  	    high = 1
  4  	    for i in range(10):
</module>

Another useful feature is setting breakpoints. This is similar to putting pdb.set_trace() in your source but allows you to do so without messing with your code. To do this you just type 'break ':

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) break 5
Breakpoint 1 at /home/sontek/code/test/fib.py:5
(Pdb) c
> /home/sontek/code/test/fib.py(5)main()
-> print high
(Pdb) list
  1  	def main():
  2  	    low = 0
  3  	    high = 1
  4  	    for i in range(10):
  5 B->	        print high
  6  	        new_high = get_new_high(low, high)
  7  	        low = high
  8  	        high = new_high 
  9  	
 10  	def get_new_high(low, high):
 11  	    return low + high
</module>

I used the 'c' command which is an abbreviation for 'continue' to resume the execution of the program since I told it to break at the first line using -m pdb. You will see when Iisted out the lines of code there is 'B->' next to line 5, letting me know I have a break point there.

To inspect what a the values of a variable is you can use 'p' which is short for 'print'. If you are looking at a variable with a long string in it you might want to use 'pp' for pretty print. You can also inspect all the local variables by typing locals():

(Pdb) locals()
{'high': 1, 'i': 0, 'low': 0}

You can also make it so that pdb will only stop if certain conditions are met by passing it to the break command or using the condition command after you've defined the breakpoint:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) break 5, i > 6
Breakpoint 1 at /home/sontek/code/test/fib.py:5
(Pdb) c
1
1
2
3
5
8
13
> /home/sontek/code/test/fib.py(5)main()
-> print high
</module>

using the condition command, I tell it I want to set the condition on the first break point:

(Pdb) break 5
Breakpoint 1 at /home/sontek/code/test/fib.py:5
(Pdb) condition 1 i > 6

If you have existing breakpoints that you want to add a condition to but don't know the number of them you can use break without any arguments and it will list all your breakpoints out:

(Pdb) break
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /home/sontek/code/test/fib.py:5

You can turn breakpoints on and off using the 'enable' and 'disable' commands or remove them completely using the 'clear' command.

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) break 5
Breakpoint 1 at /home/sontek/code/test/fib.py:5
(Pdb) break
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /home/sontek/code/test/fib.py:5
(Pdb) disable 1
(Pdb) break
Num Type         Disp Enb   Where
1   breakpoint   keep no    at /home/sontek/code/test/fib.py:5
(Pdb) enable 1
(Pdb) break
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /home/sontek/code/test/fib.py:5
(Pdb) clear 1
Deleted breakpoint 1
(Pdb) break
</module>

Once you are at a breakpoint you will want to move around to inspect your code, you can do this using the 'next' and 'step' commands which can be abbreviated 's' and 'n'. The big difference between next and step is that next will execute function calls and step will go inside them.

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) break 6
Breakpoint 1 at /home/sontek/code/test/fib.py:6
(Pdb) c
1
> /home/sontek/code/test/fib.py(6)main()
-> new_high = get_new_high(low, high)
(Pdb) n
> /home/sontek/code/test/fib.py(7)main()
-> low = high
(Pdb) c
1
> /home/sontek/code/test/fib.py(6)main()
-> new_high = get_new_high(low, high)
(Pdb) s
--Call--
> /home/sontek/code/test/fib.py(10)get_new_high()
-> def get_new_high(low, high):
(Pdb) n
> /home/sontek/code/test/fib.py(11)get_new_high()
-> return low + high
</module>

You can see when we used next it just moved to the next line but when we used step it actually went into the get_new_high function.

Instead of working off of line numbers you can also set break points on function names:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) break get_new_high
Breakpoint 1 at /home/sontek/code/test/fib.py:10
(Pdb) c
1
> /home/sontek/code/test/fib.py(11)get_new_high()
-> return low + high
(Pdb) list
  6  	        new_high = get_new_high(low, high)
  7  	        low = high
  8  	        high = new_high 
  9  	
 10 B	def get_new_high(low, high):
 11  ->	    return low + high
 12  	
 13  	if __name__ == '__main__':
 14  	    main()
</module>

You can also move up and down testing different values using the 'jump' command:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) b 5
Breakpoint 1 at /home/sontek/code/test/fib.py:5
(Pdb) c
> /home/sontek/code/test/fib.py(5)main()
-> print high
(Pdb) j 4
> /home/sontek/code/test/fib.py(4)main()
-> for i in range(10):
(Pdb) high=3
(Pdb) c
> /home/sontek/code/test/fib.py(5)main()
-> print high
(Pdb) p high
3
(Pdb) list
  1  	def main():
  2  	    low = 0
  3  	    high = 1
  4  	    for i in range(10):
  5 B->	        print high
  6  	        new_high = get_new_high(low, high)
  7  	        low = high
  8  	        high = new_high 
  9  	
 10  	def get_new_high(low, high):
 11  	    return low + high
(Pdb) j 8
> /home/sontek/code/test/fib.py(8)main()
-> high = new_high
</module>

You can also go up and down the stack inspecting what the variables were at that time:

python -m pdb fib.py
> /home/sontek/code/test/fib.py(1)<module>()
-> def main():
(Pdb) b 11
Breakpoint 1 at /home/sontek/code/test/fib.py:11
(Pdb) c
1
> /home/sontek/code/test/fib.py(11)get_new_high()
-> return low + high
(Pdb) up
> /home/sontek/code/test/fib.py(6)main()
-> new_high = get_new_high(low, high)
(Pdb) p low
0
(Pdb) down
> /home/sontek/code/test/fib.py(11)get_new_high()
-> return low + high
(Pdb) list
  6  	        new_high = get_new_high(low, high)
  7  	        low = high
  8  	        high = new_high 
  9  	
 10  	def get_new_high(low, high):
 11 B->	    return low + high
 12  	
 13  	if __name__ == '__main__':
 14  	    main()
</module>

You can inspect what arguments are being passed to a function with the 'args' command:

> /home/sontek/code/test/fib.py(11)get_new_high()
-> return low + high
(Pdb) args
low = 0
high = 1
(Pdb) 

You can also use the 'where' command to inspect where in the callstack you currently are.

If you have variables that are named the same as pdb commands like 'n' or 'break' and would like to change them you need to assign them different values in the debugger for testing use an exclamation point before the command that you want to evaluate:

!n=1

Here are some other useful resources on learning pdb:

http://docs.python.org/library/pdb.html

http://www.doughellmann.com/PyMOTW/pdb/

View Comments

Implementing Django's Admin Interface Pop-Ups

Topics: django python

In the Django admin interface there is the nice ability to dynamically add new items to foreign key fields and it'd be nice to provide that same functionality in our own interfaces. Luckily since the admin interface already has all the functionality implemented we can be good little software engineers and reuse their code instead of reinventing the wheel.

The first thing we need to do is get access to ADMIN_MEDIA_PREFIX out of the settings so that we can include some of the admin javascript in our own interface, so we'll create a template context processor to handle that.

# context_processors.py
from django.conf import settings

def admin_media_prefix(request):
    return {'ADMIN_MEDIA_PREFIX': settings.ADMIN_MEDIA_PREFIX } 

Make sure to include this new template context processor in your settings in the TEMPLATE_CONTEXT_PROCESSORS tuple.

For information on writing your own context processors: here

Then we just include the admin interface's RelatedObjectLookups.js into our template:

<script src="{{ ADMIN_MEDIA_PREFIX }}js/admin/RelatedObjectLookups.js"></script>

Now we create a custom widget that calls the javascript we just included and attach it to the foreignkey fields:

#widgets.py
from django import forms
from django.template.loader import render_to_string

class SelectWithPopUp(forms.Select):
    model = None

    def __init__(self, model=None):
        self.model = model
        super(SelectWithPopUp, self).__init__()

    def render(self, name, *args, **kwargs):
        html = super(SelectWithPopUp, self).render(name, *args, **kwargs)

        if not self.model:
            self.model = name

        popupplus = render_to_string("formpopup.html", {'field': name, 'model': self.model})
        return html+popupplus

The template code for your widget:

<a href="/add/{{ model }}/" class="add-another" id="add_id_{{ field }}" onclick="return showAddAnotherPopup(this);">
+
</a>

Now you can attach your widget to any foreignkey select field on your form:

#forms.py
from app.widgets import SelectWithPopUp

class CustomForm(forms.Form):
    selectfield = forms.ModelChoiceField(Model.objects, widget=SelectWithPopUp)

The final piece of the puzzle is to create a view that can handle the saving and creation of the dynamic form:

# views.py
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponseNotFound, HttpResponse
from django.utils.html import escape
from django.forms.models import modelform_factory
from django.db.models.loading import get_models, get_app, get_apps

@login_required
def add_new_model(request, model_name):
    if (model_name.lower() == model_name):
        normal_model_name = model_name.capitalize()
    else:
        normal_model_name = model_name

    app_list = get_apps()
    for app in app_list:
        for model in get_models(app):
            if model.__name__ == normal_model_name:
                form = modelform_factory(model)

                if request.method == 'POST':
                    form = form(request.POST)
                    if form.is_valid():
                        try:
                            new_obj = form.save()
                        except forms.ValidationError, error:
                            new_obj = None

                        if new_obj:
                            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
                                (escape(new_obj._get_pk_val()), escape(new_obj)))

                else:
                    form = form()

                page_context = {'form': form, 'field': normal_model_name}
                return render_to_response('popup.html', page_context, context_instance=RequestContext(request))

The template code for your view:

<html>
<head>
<title>Add {{ field }}</title>
<script src="{{ ADMIN_MEDIA_PREFIX }}js/admin/RelatedObjectLookups.js"></script>
</head>
<body>
<h1>Add {{ field }}</h1>
<form method="POST" action="/add/{{ field }}">
        {% csrf_token %}
        <table>
        {{ form }}
        </table>
<p><input type="submit" /> | <a href="javascript:window.close()">Cancel</a></p>
</form>
</body>
</html>

I've implemented all this code into a re-usable django application that you can just drop into your own project here.

Thank you Mimsy for the original tips on how to implement this.

View Comments

Integration Tests with Lightweight Test Automation Framework (LTAF) and ASP.NET

Topics: asp.net c# ltaf

LTAF is an integration test framework developed by the Microsoft ASP.NET QA Team. Integration tests are different than unit tests, they actually test what a user would be doing by opening up the browser and filling in textboxes or clicking links. LTAF is nice because you write your tests in C# and run them in the browser of your choice, the disadvantage to this is you can’t have it easily integrate with a continuous integration system like CruiseControl.NET since there is no runner.


To get started with LTAF, you can download the latest release from the ASP.NET QA Page on CodePlex. As of the June release they didn’t have a binary release of it, your only options are either download the source and build it yourself or grab the sample application and pull it from its bin/ folder (this is what we’ll use).  You need to steal 3 files from the sample application:



  • bin/Microsoft.Web.Testing.Lightweight.dll

  • Test/Default.aspx

  • Test/DriverPage.aspx


If you don’t want to type all this, You can download my example code here, which includes both ASP.NET WebForms and MVC examples.


Add a reference to the dll and include the Test pages in your website somewhere (I just include the whole Test/ folder). Now you are ready to write your first integration tests with LTAF. You can add your tests in their own library and reference them from your web application or just include them right in your site, LTAF will just scan all assemblys for classes marked with the [WebTestClass] attribute. First, lets create a page to test:


<asp:label runat="server" id="lblMessages">
</asp:label><asp:label runat="server" id="lblUserName">
<asp:textbox runat="server" id="txtUserName">
<asp:button runat="server" id="btnSubmit" onclick="btnSubmit_Click" text="Submit"></asp:button>
</asp:textbox></asp:label>

protected void btnSubmit_Click(object sender, EventArgs e)
{
    this.lblMessages.Text = String.Format("Hello, {0}", this.txtUserName.Text);
}

and now lets add a class called Tests.cs into the Test/ folder:


[WebTestClass]
public class Tests
{
  [WebTestMethod]
  public void Test_User_Can_Submit_UserName()
  {
    HtmlPage page = new HtmlPage("/Default.aspx");
    page.Elements.Find("txtUserName").SetText("John Anderson");
    page.Elements.Find("btnSubmit").Click(WaitFor.Postback);
    Assert.StringContains(page.Elements.Find("lblMessages").GetInnerText(), "John Anderson");
  }
}

 


You can go to your site’s Test/ folder and run your tests and that is all it takes to start doing integration tests with ASP.NET and LTAF.

View Comments

Don't host jQuery yourself, use Google!

Topics: javascript jquery

Google has a content delivery network (CDN) dedicated to serving the most popular open source JavaScript libraries here. This will give you faster delivery and better caching for your clients. The Google CDN chooses the best server to provide the library from based on the client location.

Along with location based delivery it also gives you the benefit of saving load on your server and delivering more of your local content faster. Most popular browsers limit the amount of connections from a server that can be made for downloading content and by pushing off your JavaScript loading onto Google’s servers you are freeing up connections that can be used for the rest of your application.

Currently Google hosts jQuery, Prototype, script.aculo.us, MooTools, Dojo, SWFObject, YUI, and Ext.

Older Newer