Moved the files to new Django app named scipycon and modified settings.
authorMadhusudan.C.S <madhusudancs@gmail.com>
Tue, 13 Jul 2010 17:59:47 +0530
changeset 94 87e77aa18610
parent 93 e86755df35da
child 95 f94e0cd9a862
Moved the files to new Django app named scipycon and modified settings.
AUTHORS
CHANGES
TODO
project.db
project/kiwipycon/__init__.py
project/kiwipycon/context_processors.py
project/kiwipycon/proceedings/__init__.py
project/kiwipycon/proceedings/admin.py
project/kiwipycon/proceedings/booklet/__init__.py
project/kiwipycon/proceedings/booklet/mk_booklet.py
project/kiwipycon/proceedings/booklet/mk_scipy_paper.py
project/kiwipycon/proceedings/forms.py
project/kiwipycon/proceedings/migrations/0001_initial.py
project/kiwipycon/proceedings/migrations/__init__.py
project/kiwipycon/proceedings/models.py
project/kiwipycon/proceedings/views.py
project/kiwipycon/registration/__init__.py
project/kiwipycon/registration/admin.py
project/kiwipycon/registration/forms.py
project/kiwipycon/registration/labels.py
project/kiwipycon/registration/migrations/0001_initial.py
project/kiwipycon/registration/migrations/0002_create_wifi.py
project/kiwipycon/registration/migrations/__init__.py
project/kiwipycon/registration/models.py
project/kiwipycon/registration/pdf.py
project/kiwipycon/registration/tests.py
project/kiwipycon/registration/utils.py
project/kiwipycon/registration/views.py
project/kiwipycon/sponsor/__init__.py
project/kiwipycon/sponsor/admin.py
project/kiwipycon/sponsor/migrations/0001_initial.py
project/kiwipycon/sponsor/migrations/__init__.py
project/kiwipycon/sponsor/models.py
project/kiwipycon/sponsor/views.py
project/kiwipycon/talk/__init__.py
project/kiwipycon/talk/admin.py
project/kiwipycon/talk/forms.py
project/kiwipycon/talk/migrations/0001_initial.py
project/kiwipycon/talk/migrations/__init__.py
project/kiwipycon/talk/models.py
project/kiwipycon/talk/templatetags/__init__.py
project/kiwipycon/talk/templatetags/talk_extras.py
project/kiwipycon/talk/views.py
project/kiwipycon/user/__init__.py
project/kiwipycon/user/admin.py
project/kiwipycon/user/forms.py
project/kiwipycon/user/migrations/0001_initial.py
project/kiwipycon/user/migrations/__init__.py
project/kiwipycon/user/models.py
project/kiwipycon/user/utils.py
project/kiwipycon/user/views.py
project/kiwipycon/utils.py
project/scipycon/__init__.py
project/scipycon/context_processors.py
project/scipycon/proceedings/__init__.py
project/scipycon/proceedings/admin.py
project/scipycon/proceedings/booklet/__init__.py
project/scipycon/proceedings/booklet/mk_booklet.py
project/scipycon/proceedings/booklet/mk_scipy_paper.py
project/scipycon/proceedings/forms.py
project/scipycon/proceedings/migrations/0001_initial.py
project/scipycon/proceedings/migrations/__init__.py
project/scipycon/proceedings/models.py
project/scipycon/proceedings/views.py
project/scipycon/registration/__init__.py
project/scipycon/registration/admin.py
project/scipycon/registration/forms.py
project/scipycon/registration/labels.py
project/scipycon/registration/migrations/0001_initial.py
project/scipycon/registration/migrations/0002_create_wifi.py
project/scipycon/registration/migrations/__init__.py
project/scipycon/registration/models.py
project/scipycon/registration/pdf.py
project/scipycon/registration/tests.py
project/scipycon/registration/utils.py
project/scipycon/registration/views.py
project/scipycon/sponsor/__init__.py
project/scipycon/sponsor/admin.py
project/scipycon/sponsor/migrations/0001_initial.py
project/scipycon/sponsor/migrations/__init__.py
project/scipycon/sponsor/models.py
project/scipycon/sponsor/views.py
project/scipycon/talk/__init__.py
project/scipycon/talk/admin.py
project/scipycon/talk/forms.py
project/scipycon/talk/migrations/0001_initial.py
project/scipycon/talk/migrations/__init__.py
project/scipycon/talk/models.py
project/scipycon/talk/templatetags/__init__.py
project/scipycon/talk/templatetags/talk_extras.py
project/scipycon/talk/views.py
project/scipycon/user/__init__.py
project/scipycon/user/admin.py
project/scipycon/user/forms.py
project/scipycon/user/migrations/0001_initial.py
project/scipycon/user/migrations/__init__.py
project/scipycon/user/models.py
project/scipycon/user/utils.py
project/scipycon/user/views.py
project/scipycon/utils.py
project/settings.py
project/setup.py
project/urls.py
sponsor.sql
--- a/AUTHORS	Thu Apr 01 11:59:35 2010 +0530
+++ b/AUTHORS	Tue Jul 13 17:59:47 2010 +0530
@@ -1,3 +1,9 @@
+Madhusudan.C.S <madhusudancs@fossee.in>
+
+-- Took the base code and idea from kiwipycon app and making modifications
+-- to it to take up to the level of a new customized app. Courtesy to the
+-- authors of kiwipycon app below.
+
 Marek Kuziel <marek@kuziel.info>
 
 - provided the start up of the project and fixes to Darryl's code.
--- a/CHANGES	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-6 September 2009
-----------------
-
-- added sponsor table, prepopulate from sponsor.sql
-  (need to manually add number of guests allowed per sponsor)
-- sponsor logo and credits sourced from sponsor table
-- new schwag sponsor page (generated from sponsor table)
-  (please delete current static page which this replaces)
-- added fields to registration:
-    party - pre-conference party
-    discount - student/benefits
-    sponsor - a guest of sponsor
-    postcode
-- prefixed invoice number with NZPYCON2009_****
-- added confirmation email for sponsor guests (no invoice number)
-- added payment confirmation email when admin confirms payment for 
-  registrant. (Using save() hook on Registration model
-  PDF invoice will be attached to this email.
-- link and icon to twitter account
-- removed 'submit-talk' links
-- decided that a mechanism to email all speakers or all attendees to be
-  overkill. 
-
-- added list and singleton views for talks
-- set up south migrations for apps
-
-- added further functionality to registrations to deal with price scale.
--- a/TODO	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-TODO
-====
-- Fix blog CSS
-
-STAGE2
-======
-- kiwipycon/conference (don't add until we release site with call for papers)
-  - models (Resistration)
-  - the nzpug incorporated soc a/c
-
-PERPETUAL
-=========
-- Unittests
Binary file project.db has changed
--- a/project/kiwipycon/context_processors.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-from datetime import datetime
-
-from django.conf import settings
-
-from project.kiwipycon.sponsor.models import Sponsor
-
-def sponsors(request):
-    sponsors = Sponsor.objects.all()
-    gold_sponsors = sponsors.filter(type='gold')
-    silver_sponsors = sponsors.filter(type='silver')
-    schwag_sponsors = sponsors.filter(type='schwag')
-    return {
-            'sponsors': {'gold': gold_sponsors,
-                         'silver': silver_sponsors,
-                         'schwag': schwag_sponsors}
-    }
-
--- a/project/kiwipycon/proceedings/admin.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-from django.contrib import admin
-
-from project.kiwipycon.proceedings.models import Paper
-
-
-class PaperAdmin(admin.ModelAdmin):
-    list_display = ('title', 'abstract')
-    list_filter = ('title', 'authors')
-    search_fields = ('title', 'abstract', 'authors')
-    fieldsets = (
-        ('Details', {
-            'fields': ('title', 'abstract', 'body', 'authors')
-        }),
-    )
-
-admin.site.register(Paper, PaperAdmin)
--- a/project/kiwipycon/proceedings/booklet/mk_booklet.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-# encoding: utf-8
-
-import os
-import sys
-import codecs
-import re
-
-try:
-    from sanum import model
-except:
-    root_dir = os.path.abspath(os.getcwd() + '/../../')
-    os.chdir(root_dir)
-    sys.path.append(root_dir)
-    from sanum import model
-
-import sanum
-
-import turbogears
-turbogears.update_config(configfile="dev.cfg",
-                         modulename="sanum.config")
-
-
-from mk_scipy_paper import tex2pdf, current_dir , copy_files, preamble, \
-        render_abstract, addfile, sourcedir, outdir, outfilename
-
-
-def hack_include_graphics(latex_text, attach_dir):
-    """ Replaces all the \includegraphics call with call that impose the
-        width to be 0.9\linewidth.
-    """
-    latex_text = re.sub(r'\\includegraphics(\[.*\])?\{',
-                        r'\includegraphics\1{' + attach_dir,
-                        latex_text)
-    return latex_text
-
-
-class MyStringIO(object):
-    """ An unicode-friendly stringIO-like object.
-    """
-
-    def __init__(self):
-        self.lines = []
-
-    def write(self, line):
-        self.lines.append(line)
-
-    def getvalue(self):
-        return u''.join(self.lines)
-
-def mk_booklet_tex(outfilename):
-    """ Generate the entire booklet latex file.
-    """
-    outfile = codecs.open(outfilename, 'w', 'utf-8')
-    preamble(outfile)
-    copy_files()
-    #addfile(outfile, sourcedir + os.sep + 'title.tex')
-    addfile(outfile, sourcedir + os.sep + 'introduction.tex')
-
-    #outfile.write(ur'\setcounter{page}{0}' + '\n')
-
-    #from sanum.controllers import Root as Controller
-    abstracts = model.Abstract.select()
-    for abstract in abstracts:
-        if not abstract.approved:
-            continue
-        print abstract.title
-        # Hack: I don't use a stringIO, because it is not unicode-safe.
-        tmpout = MyStringIO()
-        # Hack: I don't wont to be bound to the controller, to be
-        # abstractle to run without cherrypy.
-        #attach_dir = Controller._paper_attach_dir(abstract.id)
-        attach_dir = os.path.abspath(os.sep.join(
-                    (os.path.dirname(sanum.__file__), 'static', 
-                    'papers', '%i' % abstract.id))) + os.sep
-        render_abstract(tmpout, abstract)
-        outstring = hack_include_graphics(tmpout.getvalue(),
-                            attach_dir)
-        outfile.write(outstring)
-        #outfile.write(ur'\fillbreak' + '\n')
-
-    outfile.write(ur'\end{document}' + '\n')
-
-
-
-
-def mk_booklet(outfilename=outfilename):
-    """ Generate the entire booklet pdf file.
-    """
-    name, ext = os.path.splitext(outfilename)
-    mk_booklet_tex(name + '.tex')
-    return tex2pdf(name, remove_tex=False, timeout=60)
-
-if __name__ == '__main__':
-    mk_booklet(outfilename)
--- a/project/kiwipycon/proceedings/booklet/mk_scipy_paper.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,463 +0,0 @@
-# encoding: utf-8
-
-import os
-import re
-import sys
-import shutil
-import codecs
-from glob import glob
-
-from docutils import core as docCore
-
-conf_name = 'SciPy2009'
-
-current_dir = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet'
-
-outdir = current_dir + os.sep + 'output'
-
-sourcedir = current_dir + os.sep + 'sources'
-try:
-    os.mkdir(outdir)
-except:
-    pass
-
-outfilename = outdir + os.sep + 'booklet.tex'
-
-##############################################################################
-# Routines for supervised execution
-##############################################################################
-
-from threading import Thread
-import os
-import signal
-from subprocess import Popen
-from time import sleep
-
-def delayed_kill(pid, delay=10):
-    sleep(delay)
-    try:
-        os.kill(pid, signal.SIGTERM)
-    except OSError:
-        pass
-
-def supervise_popen(command, timeout=10):
-    process = Popen(command)
-    Thread(target=delayed_kill, args=(process.pid,timeout),).start()
-
-    process.wait()
-
-
-
-##############################################################################
-# LaTeX generation functions.
-##############################################################################
-
-def protect(string):
-    r''' Protects all the "\" in a string by adding a second one before
-
-    >>> protect(r'\foo \*')
-    '\\\\foo \\\\*'
-    '''
-    return re.sub(r"\\", r"\\\\", string)
-
-
-def safe_unlink(filename):
-    """ Remove a file from the disk only if it exists, if not r=fails silently
-    """
-    if os.path.exists(filename):
-        os.unlink(filename)
-
-rxcountpages = re.compile(r"$\s*/Type\s*/Page[/\s]", re.MULTILINE|re.DOTALL)
-
-def count_pages(filename):
-    data = file(filename,"rb").read()
-    return len(rxcountpages.findall(data))
-
-
-def tex2pdf(filename, remove_tex=True, timeout=10, runs=2):
-    """ Compiles a TeX file with pdfLaTeX (or LaTeX, if or dvi ps requested)
-        and cleans up the mess afterwards
-    """
-    current_dir = os.getcwd()
-    os.chdir(os.path.dirname(filename))
-    print >> sys.stderr, "Compiling document to pdf"
-    basename = os.path.splitext(os.path.basename(filename))[0]
-    if os.path.exists(basename + '.pdf'):
-        os.unlink(basename + '.pdf')
-    for _ in range(runs):
-        supervise_popen(("pdflatex",  "--interaction", "scrollmode",
-                        os.path.basename(filename)), timeout=timeout)
-    error_file = None
-    errors =  file(os.path.abspath(basename + '.log')).readlines()[-1]
-    if not os.path.exists(basename + '.pdf') or \
-                                    "Fatal error" in errors:
-        error_file = os.path.abspath(basename + '.log')
-    if remove_tex:
-        safe_unlink(filename+".tex")
-        safe_unlink(filename+".log")
-    safe_unlink(filename+".aux")
-    safe_unlink(filename+".out")
-    os.chdir(current_dir)
-    return error_file
-
-
-def rst2latex(rst_string, no_preamble=True, allow_latex=True):
-    """ Calls docutils' engine to convert a rst string to a LaTeX file.
-    """
-    overrides = {'output_encoding': 'utf-8', 'initial_header_level': 3,
-                 'no_doc_title': True, 'use_latex_citations': True, 
-                 'use_latex_footnotes':True}
-    if allow_latex:
-        rst_string = u'''.. role:: math(raw)
-                    :format: latex
-                    \n\n''' + rst_string
-    tex_string = docCore.publish_string(
-                source=rst_string,
-                writer_name='latex2e', 
-                settings_overrides=overrides)
-    if no_preamble:
-        extract_document = \
-            re.compile(r'.*\\begin\{document\}(.*)\\end\{document\}',
-            re.DOTALL)
-        matches = extract_document.match(tex_string)
-        tex_string = matches.groups()[0]
-    return tex_string
-
-
-def get_latex_preamble():
-    """ Retrieve the required preamble from docutils.
-    """
-    full_document = rst2latex('\n', no_preamble=False)
-    preamble = re.split(r'\\begin\{document\}', full_document)[0]
-    ## Remove the documentclass.
-    preamble = r"""
-                %s
-                \makeatletter
-                \newcommand{\class@name}{gael}
-                \makeatother
-                \usepackage{ltxgrid}
-                %s
-                """ % (
-                    preamble.split('\n')[0],
-                    '\n'.join(preamble.split('\n')[1:]),
-                )
-    return preamble
-
-
-##############################################################################
-# Functions to generate part of the booklet
-##############################################################################
-def addfile(outfile, texfilename):
-    """ Includes the content of a tex file in our outfile.
-    """
-    include = codecs.open(texfilename, 'r')
-    data = include.readlines()
-    outfile.write(ur'\thispagestyle{empty}' + u'\n')
-    outfile.writelines(data)
-
-
-def preamble(outfile):
-    outfile.write(r'''
-    %s
-    \usepackage{abstracts}
-    \usepackage{ltxgrid}
-    \usepackage{amssymb,latexsym,amsmath,amsthm}
-    \usepackage{longtable}
-    \geometry{left=.8cm, textwidth=17cm, bindingoffset=0.6cm,
-                textheight=25.3cm, twoside}
-    \usepackage{hyperref}
-    \hypersetup{pdftitle={Proceedings of the 8th Annual Python in Science Conference}}
-    \begin{document}
-
-    '''.encode('utf-8') % get_latex_preamble())
-
-    # XXX SciPy08 should not be hard coded, but to run out of the webapp
-
-def hack_include_graphics(latex_text):
-    """ Replaces all the \includegraphics call with call that impose the
-        width to be 0.9\linewidth.
-    """
-    latex_text = re.sub(r'\\setlength\{\\rightmargin\}\{\\leftmargin\}',
-                        r'\\setlength{\\leftmargin}{4ex}\\setlength{\\rightmargin}{0ex}',
-                        latex_text)
-    latex_text = re.sub(r'\\begin\{quote\}\n\\begin\{itemize\}',
-                        r'\\begin{itemize}',
-                        latex_text)
-    latex_text = re.sub(r'\\end\{itemize\}\n\\end\{quote\}',
-                        r'\\end{itemize}',
-                        latex_text)
-    latex_text = re.sub(r'\\includegraphics(\[.*\])?\{',
-                        r'\includegraphics[width=\linewidth]{',
-                        latex_text)
-    latex_text = re.sub(r'\\href\{([^}]+)\}\{http://(([^{}]|(\{[^}]*\}))+)\}', 
-                        r'''%
-% Break penalties to have URL break easily:
-\mathchardef\UrlBreakPenalty=0
-\mathchardef\UrlBigBreakPenalty=0
-%\hskip 0pt plus 2em
-\href{\1}{\url{\1}}''',
-                        latex_text)
-    latex_text = re.sub(r'\\href\{([^}]+)\}\{https://(([^{}]|(\{[^}]*\}))+)\}', 
-                        r'''%
-% Break penalties to have URL break easily:
-\mathchardef\UrlBreakPenalty=0
-\mathchardef\UrlBigBreakPenalty=0
-\linebreak
-\href{\1}{\url{\1}}''',
-                        latex_text)
-
-    return latex_text
-
-
-def render_abstract(outfile, abstract, start_page=None):
-    """ Writes the LaTeX string corresponding to one abstract.
-    """
-    if start_page is not None:
-        outfile.write(r"""
-\setcounter{page}{%i}
-""" % start_page)
-    else:
-        if hasattr(abstract, 'start_page'):
-            start_page = abstract.start_page
-        else:
-            start_page = 1
-    if not abstract.authors:
-        author_list = abstract.owners
-    else:
-        author_list = abstract.authors
-    authors = []
-    print dir(author_list[0])
-    for author in author_list:
-        # If the author has no surname, he is not an author 
-        if author.surname:
-            if author.email_address:
-                email = r'(\email{%s})' % author.email_address
-            else:
-                email = ''
-            authors.append(ur'''\otherauthors{
-                            %s %s
-                            %s --
-                            \address{%s, %s}
-                            }''' % (author.first_names, author.surname,
-                                    email,
-                                    author.institution,
-                                    author.city))
-    if authors:
-        authors = u'\n'.join(authors)
-        authors += r'\addauthorstoc{%s}' % ', '.join(
-                '%s. %s' % (author.first_names[0], author.surname)
-                for author in author_list
-                )
-        author_cite_list = ['%s. %s' % (a.first_names[0], a.surname) 
-                                for a in author_list]
-        if len(author_cite_list) > 4:
-            author_cite_list = author_cite_list[:3]
-            author_cite_list.append('et al.')
-        citation = ', '.join(author_cite_list) + \
-        'in Proc. SciPy 2009, G. Varoquaux, S. van der Walt, J. Millman (Eds), '
-        copyright = '\\copyright 2009, %s' % ( ', '.join(author_cite_list))
-    else:
-        authors = ''
-        citation = 'Citation'
-        copyright = 'Copyright'
-    if hasattr(abstract, 'num_pages'):
-        citation += 'pp. %i--%i' % (start_page, start_page +
-                                        abstract.num_pages)
-    else:
-        citation += 'p. %i'% start_page
-    if hasattr(abstract, 'number'):
-        abstract.url = 'http://conference.scipy.org/proceedings/%s/paper_%i' \
-        % (conf_name, abstract.number)
-        url = r'\url{%s}' % abstract.url
-    else:
-        url = ''
-    paper_text = abstract.paper_text
-    if paper_text == '':
-        paper_text = abstract.summary
-    # XXX: It doesn't seem to be right to be doing this, but I get a
-    # nasty UnicodeDecodeError on some rare abstracts, elsewhere.
-    paper_text = codecs.utf_8_decode(hack_include_graphics(
-                                rst2latex(paper_text)))[0]
-    paper_abstract = abstract.paper_abstract
-    if paper_abstract is None:
-        paper_abstract = ''
-    if not paper_abstract=='':
-        paper_abstract = ur'\begin{abstract}%s\end{abstract}' % \
-                    paper_abstract#.encode('utf-8')
-    abstract_dict = {
-            'text': paper_text.encode('utf-8'),
-            'abstract': paper_abstract.encode('utf-8'),
-            'authors': authors.encode('utf-8'),
-            'title': abstract.title.encode('utf-8'),
-            'citation': citation.encode('utf-8'),
-            'copyright': copyright.encode('utf-8'),
-            'url': url.encode('utf-8'),
-        }
-    outfile.write(codecs.utf_8_decode(ur'''
-\phantomsection
-\hypertarget{chapter}{} 
-\vspace*{-2em}
-
-\resetheadings{%(title)s}{%(citation)s}{%(url)s}{%(copyright)s}
-\title{%(title)s}
-
-\begin{minipage}{\linewidth}
-%(authors)s
-\end{minipage}
-
-\noindent\rule{\linewidth}{0.2ex}
-\vspace*{-0.5ex}
-\twocolumngrid
-%(abstract)s
-
-\sloppy
-
-%(text)s
-
-\fussy
-\onecolumngrid
-\smallskip
-\vfill
-\filbreak
-\clearpage
-
-'''.encode('utf-8') % abstract_dict )[0])
-
-def copy_files(dest=outfilename):
-    """ Copy the required file from the source dir to the output dir.
-    """
-    dirname = os.path.dirname(dest)
-    if dirname == '':
-        dirname = '.'
-    for filename in glob(sourcedir+os.sep+'*'):
-        destfile = os.path.abspath(dirname + os.sep +
-                                os.path.basename(filename))
-        shutil.copy2(filename, destfile)
-
-
-def mk_abstract_preview(abstract, outfilename, attach_dir, start_page=None):
-    """ Generate a preview for an given paper.
-    """
-    copy_files()
-    outdir = os.path.dirname(os.path.abspath(outfilename))
-    for f in glob(os.path.join(attach_dir, '*')):
-        if  os.path.isdir(f) and not os.path.exists(f):
-            os.makedirs(f)
-        else:
-            if not outdir == os.path.dirname(os.path.abspath(f)):
-                shutil.copy2(f, outdir)
-    for f in glob(os.path.join(sourcedir, '*')):
-        if  os.path.isdir(f):
-            os.makedirs(f)
-        else:
-            destfile = os.path.abspath(os.path.join(outdir, f))
-            shutil.copy2(f, outdir)
-
-    outbasename = os.path.splitext(outfilename)[0]
-    outfilename = outbasename + '.tex'
-
-    outfile = codecs.open(outfilename, 'w', 'utf-8')
-    preamble(outfile)
-    render_abstract(outfile, abstract, start_page=start_page)
-    outfile.write(ur'\end{document}' + u'\n')
-    outfile.close()
-
-    tex2pdf(outbasename, remove_tex=False)
-    abstract.num_pages = count_pages(outbasename + '.pdf')
-
-    # Generate the tex file again, now that we know the length.
-    outfile = codecs.open(outfilename, 'w', 'utf-8')
-    preamble(outfile)
-    render_abstract(outfile, abstract, start_page=start_page)
-    outfile.write(ur'\end{document}' + u'\n')
-    outfile.close()
-
-    return tex2pdf(os.path.splitext(outfilename)[0], remove_tex=False)
-
-
-##############################################################################
-# Code for using outside of the webapp.
-##############################################################################
-
-def mk_zipfile():
-    """ Generates a zipfile with the required files to build an
-        abstract.
-    """
-    from zipfile import ZipFile
-    zipfilename = os.path.join(os.path.dirname(__file__), 
-                            'mk_scipy_paper.zip')
-    z = ZipFile(zipfilename, 'w')
-    for filename in glob(os.path.join(sourcedir, '*')):
-        if not os.path.isdir(filename):
-            z.write(filename, arcname='source/' + os.path.basename(filename))
-    z.write(__file__, arcname='mk_scipy_paper.py')
-    return zipfilename
-
-class Bunch(dict):
-    def __init__(self, **kwargs):
-        dict.__init__(self, **kwargs)
-        self.__dict__ = self
-
-    def __reprt(self):
-        return repr(self.__dict__)
-
-author_like = Bunch(
-        first_names='XX', 
-        surname='XXX',
-        email_address='xxx@XXX',
-        institution='XXX',
-        address='XXX',
-        country='XXX'
-)
-
-
-abstract_like = Bunch(
-        paper_abstract='An abstract',
-        authors=[author_like, ],
-        title='',
-    )
-
-if __name__ == '__main__':
-    from optparse import OptionParser
-    parser = OptionParser()
-    parser.add_option("-o", "--output", dest="outfilename",
-                    default="./paper.pdf",
-                    help="output to FILE", metavar="FILE")
-    parser.usage = """%prog [options] rst_file [data_file]
-    Compiles a given rest file and information file to pdf for the SciPy
-    proceedings.
-    """
-    
-    (options, args) = parser.parse_args()
-    if not len(args) in (1, 2):
-        print "One or two arguments required: the input rest file and " \
-                "the input data file"
-        print ''
-        parser.print_help()
-        sys.exit(1)
-    infile = args[0]
-    if len(args)==1:
-        data_file = 'data.py'
-        if os.path.exists('data.py'):
-            print "Using data file 'data.py'"
-        else:
-            print "Generating the data file and storing it in data.py"
-            print "You will need to edit this file to add title, author " \
-                "information, and abstract."
-            abstract = abstract_like
-            file('data.py', 'w').write(repr(abstract))
-    elif len(args)==2:
-        data_file = args[1]
-    
-    abstract = Bunch( **eval(file(data_file).read()))
-    abstract.authors = [Bunch(**a) for a in abstract.authors]
-
-    abstract['summary'] = u''
-    abstract['paper_text'] = file(infile).read().decode('utf-8')
-
-    outfilename = options.outfilename
-
-    mk_abstract_preview(abstract, options.outfilename, 
-                        os.path.dirname(options.outfilename))
-    # Ugly, but I don't want to wait on the thread.
-    sys.exit()
--- a/project/kiwipycon/proceedings/forms.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from django import forms
-
-
-class ProceedingsForm(forms.Form):
-    """Form for proceedings.
-    """
-
-    title = forms.CharField(required=True, label=u'Title',
-                            widget=forms.TextInput(attrs={'size':'70'}))
-
-    abstract = forms.CharField(
-        widget=forms.Textarea(attrs={'cols': '80', 'rows': '8'}),
-        required=True, label=u'Abstract',
-        help_text=u'Upto 200 words. Content must strictly be in reSt format.')
-
-    body = forms.CharField(
-        widget=forms.Textarea(attrs={'cols': '80', 'rows': '25'}),
-        required=False, label=u'Body', help_text=u'Approximately 7 pages. '
-        'Content must strictly be in reSt format.')
-
-    rst_file = forms.FileField(
-        required=False, label=u'reStructuredText file',
-        help_text=u'The file should contain two sections, one with a heading '
-        "'Abstract' and other with a heading 'Body'.")
-
-    authors = forms.CharField(
-        required=False, label=u'Author(s)',
-        help_text=u'Comma separated list of User ID of the author(s).')
--- a/project/kiwipycon/proceedings/migrations/0001_initial.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from south.db import db
-from django.db import models
-from project.kiwipycon.proceedings.models import *
-
-class Migration:
-    
-    def forwards(self, orm):
-        
-        # Adding model 'Paper'
-        db.create_table('proceedings_paper', (
-            ('body', models.TextField()),
-            ('abstract', models.TextField()),
-            ('id', models.AutoField(primary_key=True)),
-            ('title', models.CharField(max_length=200)),
-        ))
-        db.send_create_signal('proceedings', ['Paper'])
-        
-        # Adding model 'Attachments'
-        db.create_table('proceedings_attachments', (
-            ('paper', models.ForeignKey(orm.Paper)),
-            ('id', models.AutoField(primary_key=True)),
-            ('attachments', models.FileField(upload_to='attachments/%Y/%m/%d')),
-        ))
-        db.send_create_signal('proceedings', ['Attachments'])
-        
-        # Adding ManyToManyField 'Paper.authors'
-        db.create_table('proceedings_paper_authors', (
-            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
-            ('paper', models.ForeignKey(Paper, null=False)),
-            ('user', models.ForeignKey(User, null=False))
-        ))
-        
-    
-    
-    def backwards(self, orm):
-        
-        # Deleting model 'Paper'
-        db.delete_table('proceedings_paper')
-        
-        # Deleting model 'Attachments'
-        db.delete_table('proceedings_attachments')
-        
-        # Dropping ManyToManyField 'Paper.authors'
-        db.delete_table('proceedings_paper_authors')
-        
-    
-    
-    models = {
-        'proceedings.paper': {
-            'abstract': ('models.TextField', [], {}),
-            'authors': ('models.ManyToManyField', ['User'], {}),
-            'body': ('models.TextField', [], {}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'title': ('models.CharField', [], {'max_length': '200'})
-        },
-        'auth.user': {
-            '_stub': True,
-            'id': ('models.AutoField', [], {'primary_key': 'True'})
-        },
-        'proceedings.attachments': {
-            'attachments': ('models.FileField', [], {'upload_to': "'attachments/%Y/%m/%d'"}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'paper': ('models.ForeignKey', ['Paper'], {})
-        }
-    }
-    
-    complete_apps = ['proceedings']
--- a/project/kiwipycon/proceedings/models.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-from django.db import models
-from django.contrib.auth.models import User
-
-
-class Paper(models.Model):
-    """Data model for storing proceedings paper.
-    """
-
-    # Title of the paper
-    title = models.CharField(max_length=200)
-
-    # Abstract to be published with the paper
-    abstract = models.TextField()
-
-    # Body text of the paper
-    body = models.TextField()
-
-    # Authors
-    authors = models.ManyToManyField(User)
-
-
-class Attachments(models.Model):
-    """Stores attachments for papers.
-    """
-
-    # Attachment for generating paper
-    attachments = models.FileField(upload_to='attachments/%Y/%m/%d')
-
-    # The paper to which this attachment belongs to
-    paper = models.ForeignKey(Paper)
--- a/project/kiwipycon/proceedings/views.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-  # -*- coding: utf-8 -*-
-
-import os
-
-from django.contrib.auth import login
-from django.contrib.auth.decorators import login_required
-from django.contrib.auth.forms import AuthenticationForm
-from django.contrib.auth.models import User
-from django.core.urlresolvers import reverse
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-
-from project.kiwipycon.proceedings.models import Paper
-from project.kiwipycon.user.forms import RegisterForm
-from project.kiwipycon.user.models import UserProfile
-from project.kiwipycon.utils import set_message_cookie
-from project.kiwipycon.proceedings.booklet import mk_scipy_paper
-from project.kiwipycon.proceedings.forms import ProceedingsForm
-
-
-def handleUploadedFile(proceedings_form_data, rst_file):
-    """Handles the uploaded file content and process the form
-    """
-
-    title = proceedings_form_data.get('title')
-    abstract = proceedings_form_data.get('abstract')
-    body = proceedings_form_data.get('body')
-    authors = proceedings_form_data.get('authors')
-
-    if rst_file:
-        destination = open('some/file/name.txt', 'wb+')
-        for chunk in rst_file.chunks():
-            destination.write(chunk)
-        destination.close()
-
-    return title, abstract, body, authors
-
-
-@login_required
-def submit(request, id=None, template='proceedings/submit.html'):
-    """View to submit the proceedings paper.
-    """
-
-    user = request.user
-    if user.is_authenticated():
-        try:
-            profile = user.get_profile()
-        except:
-            profile, new = UserProfile.objects.get_or_create(user=user)
-            if new:
-                profile.save()
-    message = None
-
-    if request.method == 'POST':
-        register_form = RegisterForm(data=request.POST)
-
-        if request.POST.get('action', None) == 'login':
-            login_form = AuthenticationForm(data=request.POST)
-            if login_form.is_valid():
-
-                login(request, login_form.get_user())
-
-                redirect_to = reverse('kiwipycon_submit_proceedings')
-                return set_message_cookie(redirect_to,
-                        msg = u'You have been logged in.')
-
-        if request.POST.get('action', None) == 'register':
-            # add the new user
-            if register_form.is_valid():
-
-                user = kiwipycon_createuser(request, register_form.data)
-
-        proceedings_form = ProceedingsForm(data=request.POST,
-                                           files=request.FILES)
-  
-        if proceedings_form.is_valid():
-            if user.is_authenticated():
-                # Data from reSt file is appended to the data in fields
-                title, abstract, body, authors = handleUploadedFile(
-                    proceedings_form.cleaned_data, request.FILES.get('file'))
-
-                paper = edit(id, title=title,
-                    abstract=abstract, body=body,
-                    authors=authors) if id else create(title=title,
-                    abstract=abstract, body=body,
-                    authors=authors)
-
-                # Successfully saved. So get back to the edit page.
-                redirect_to = reverse('kiwipycon_submit_proceedings',
-                                  args=[paper.id])
-                return set_message_cookie(
-                redirect_to, msg = u'Thanks, your paper has been submitted.')
-            else:
-                # This is impossible. Something was wrong so return back
-                # to submit page
-                redirect_to = reverse('kiwipycon_submit_proceedings')
-                return set_message_cookie(
-                redirect_to, msg = u'Something is wrong here.')          
-    else:
-        if id:
-            # If id exists initialize the form with old values
-            paper = Paper.objects.get(id=id)
-            proceedings_form = ProceedingsForm(
-                initial={'title': paper.title,
-                         'abstract': paper.abstract,
-                         'body': paper.body,
-                         'authors': ', '.join([
-                             author.username for author in paper.authors.all()])
-                })
-        else:
-            # Otherwise create a new form
-            proceedings_form = ProceedingsForm()
-
-        register_form = RegisterForm()
-        login_form = AuthenticationForm()
-
-    context = RequestContext(request, {
-        'proceedings_form': proceedings_form,
-        'register_form' : register_form,
-        'message' : message,
-        'login_form' : login_form
-        })
-
-    context['id'] = id if id else None
-
-    return render_to_response(template, context)
-
-
-def create(**kwargs):
-    """View to create a new proceedings.
-    """
-
-    title = kwargs.get('title')
-    abstract = kwargs.get('abstract')
-    body = kwargs.get('body')
-    authors = kwargs.get('authors')
-
-    paper = Paper(title=title, abstract=abstract, body=body)
-    paper.save()
-
-    if authors:
-        authors = authors.split(',')
-        for author in authors:
-            user = User.objects.get(username=author.strip())
-            paper.authors.add(user)
-
-    return paper
-
-
-def edit(id, **kwargs):
-    """View to edit the proceedings paper.
-    """
-
-    paper = Paper.objects.get(id=id)
-
-    paper.title = kwargs.get('title')
-    paper.abstract = kwargs.get('abstract')
-    paper.body = kwargs.get('body')
-    authors = kwargs.get('authors')
-
-    if authors:
-        authors = authors.split(',')
-        for author in authors:
-            user = User.objects.get(username=author.strip())
-            paper.authors.add(user)
-
-    paper.save()
-
-    return paper
-
-
-def show_paper(request, id):
-    """Display the thumbnail of the rendered paper for download
-    """
-    
-    paper = Paper.objects.get(id=id)
-
-    paper_data = {
-      'paper_abstract': paper.abstract,
-      'authors': [
-          {'first_names': author.first_name,
-            'surname': author.last_name,
-            'address': 'XXX',
-            'country': 'XXX',
-            'email_address': 'XXX@xx.com',
-            'institution': 'XXX'
-           } for author in paper.authors.all()],
-      'title': paper.title
-      }
-    
-    abstract = mk_scipy_paper.Bunch(**paper_data)
-    abstract.authors = [mk_scipy_paper.Bunch(**a) for a in abstract.authors]
-
-    abstract['paper_text'] = paper.body
-
-    outfilename = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet/output/paper.pdf'
-    attach_dir = os.path.dirname('/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet/output/')
-    mk_scipy_paper.mk_abstract_preview(abstract, outfilename, attach_dir)
-
-    from django.http import HttpResponse
-    return HttpResponse('Machi')
-
- 
\ No newline at end of file
--- a/project/kiwipycon/registration/admin.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django.contrib
-from django.contrib import admin
-
-#kiwipycon
-from .models import Registration
-from .models import Wifi
-
-class RegistrationAdmin(admin.ModelAdmin):
-    list_display = ('registrant', 'full_name', 'laptop', 'slug',
-            'email', 'city', 'organisation', 'occupation',
-            'postcode', 'tshirt', 'conference', 'tutorial',
-            'sprint', 'allow_contact')
-    fieldsets = (
-        ('Details', {
-            'fields': ('slug', 'registrant', 'organisation', 'occupation',
-                'city', 'tshirt')
-        }),
-        ('Information', {
-            'fields': ('allow_contact',),
-        }),
-    )
-
-    search_fields = ['registrant__username', 'registrant__email']
-
-    def email(self, obj):
-        return obj.registrant.email
-
-    def full_name(self, obj):
-        return obj.registrant.get_full_name()
-
-    def laptop(self, obj):
-        return obj.registrant.wifi_set.values()[0]['wifi']
-
-admin.site.register(Registration, RegistrationAdmin)
-
-class WifiAdmin(admin.ModelAdmin):
-    list_display = ('user', 'wifi',)
-    list_filter = ('wifi',)
-
-admin.site.register(Wifi, WifiAdmin)
-
--- a/project/kiwipycon/registration/forms.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django import forms
-from django.core.exceptions import ObjectDoesNotExist
-
-#django.contrib
-from django.contrib.auth.models import User
-
-from .models import SIZE_CHOICES
-from .models import Registration
-from .models import Wifi
-from project.kiwipycon.sponsor.models import Sponsor
-
-class RegistrationSubmitForm(forms.Form):
-    """PyCon registration form
-    """
-    tshirt = forms.ChoiceField(choices=SIZE_CHOICES, required=True,
-        label=u'T-shirt size', help_text=u'Yes, we all get a t-shirt!')
-#    beverage = forms.CharField(required=True, label=u'Beverage',
-#        help_text=u'Your beverage of choice - coffee, tea etc',
-#        max_length=255,
-#        widget=forms.TextInput(attrs={'size':'50'}))
-#    diet = forms.CharField(required=False, label=u'Dietary',
-#        help_text=u'Special dietary requirements - vegetarian etc',
-#        max_length=255,
-#        widget=forms.TextInput(attrs={'size':'50'}))
-    organisation = forms.CharField(required=True, label=u'Organisation',
-        help_text=u'The primary organisation that you are a member of.',
-        max_length=255,
-        widget=forms.TextInput(attrs={'size':'50'}))
-    occupation = forms.CharField(required=True, label=u'Occupation',
-        help_text=u'Title of your occupation',
-        max_length=255,
-        widget=forms.TextInput(attrs={'size':'50'}))
-    city = forms.CharField(required=True, label=u'City',
-        help_text=u'City of residence',
-        max_length=255,
-        widget=forms.TextInput(attrs={'size':'50'}))
-    postcode = forms.CharField(required=False, label=u'Postcode',
-        help_text=u'This field is optional',
-        max_length=10,
-        widget=forms.TextInput(attrs={'size':'10'}))
-    allow_contact = forms.BooleanField(required=False, label=u'Contact',
-        help_text=u'May organizers of SciPy.in contact you after the event?')
-    conference = forms.BooleanField(required=False, label=u'Conference',
-        help_text=u"""Do you intend to attend the SciPy conference?  
-        Note: Only conference has an registration fee of Rs.200 which you will
-        pay on the spot.""")
-    tutorial = forms.BooleanField(required=False, label=u'Tutorial',
-        help_text=u'Do you intend to attend the tutorials?')
-    sprint = forms.BooleanField(required=False, label=u'Sprint',
-        help_text=u'Do you intend to attend the sprints?')
-#    party = forms.BooleanField(required=False, label=u'Pre-con party',
-#        help_text=u'Do you intend to attend the pre-conference party on Friday?')
-#    discount = forms.BooleanField(required=False, label=u'Student/Unwaged?',
-#        help_text=u'You will be required to present your Community Services '\
-#                'Card or Student ID on arrival.')
-#    sponsor = forms.CharField(required=False, label=u'Sponsor code',
-#        help_text=u'If attending as a sponsor please enter your sponsor code.',
-#        max_length=50,
-#        widget=forms.TextInput(attrs={'size':'20'}))
-
-    def demographic_fields(self):
-        return (self['organisation'],
-                self['occupation'],
-                self['city'],
-                self['postcode'])
-
-    def personal_fields(self):
-        return (self['tshirt'],
-                self['conference'],
-                self['tutorial'],
-                self['sprint'],
-                self['allow_contact'])
-
-#    def other_fields(self):
-#        return (self['sponsor'],)
-#
-#    def clean_sponsor(self):
-#        """Validates that the entered sponsor code is valid and within limits
-#        of allowed guests
-#        """
-#        sponsorcode = self.cleaned_data.get("sponsor")
-#        if sponsorcode:
-#            try:
-#                sponsor = Sponsor.objects.get(slug=sponsorcode)
-#            except ObjectDoesNotExist:
-#                raise forms.ValidationError(
-#                    u"The sponsor code you entered is not valid.")
-#            if sponsor:
-#                guests = sponsor.guests
-#                if guests == 0:
-#                    raise forms.ValidationError(
-#                        u"The sponsor code you entered is not valid.")
-#                count = Registration.objects.filter(
-#                            sponsor=sponsorcode).count()
-#                if count >= guests:
-#                    raise forms.ValidationError(
-#                    u"That sponsor has reached limit of guests.")
-#
-#
-#        return sponsorcode
-
-
-class RegistrationEditForm(RegistrationSubmitForm):
-    id = forms.CharField(widget=forms.HiddenInput)
-    sponsor = forms.CharField(required=False, widget=forms.HiddenInput)
-
-class WifiForm(forms.ModelForm):
-    """PyCon wifi form
-    """
-
-    def save(self, user):
-        wifi = Wifi(user=user, wifi=self.cleaned_data['wifi'])
-        wifi.save()
-        return wifi
-
-    class Meta:
-        model = Wifi
-        fields = ('wifi',)
-
-PC = (
-        ('all', 'all'),
-        ('paid', 'paid'),
-        ('not paid', 'not paid')
-        )
-HC = (
-        ('all', 'all'),
-        ('party', 'party'),
-        ('no party', 'no party')
-        )
-AC = (
-        ('all', 'all'),
-        ('0', '0'),
-        ('10', '10'),
-        ('20', '20'),
-        ('40', '40'),
-        )
-OC = (
-        ('email', 'email'),
-        ('amount', 'amount'),
-        )
-
-IC = (
-        ('Name', 'name'),
-        ('Email', 'email'),
-        ('Amount', 'amount'),
-        ('Organisation', 'organisation'),
-        ('Conference', 'conference'),
-        ('Tutorial', 'tutorial'),
-        ('Sprint', 'sprint'),
-        ('T-size', 'tshirt'),
-        )
-
-SC = (
-    ('all', 'all'),
-    ('S', 'S'),
-    ('M', 'M'),
-    ('L', 'L'),
-    ('XL', 'XL'),
-    )
-class RegistrationAdminSelectForm(forms.Form):
-    """
-    Used to make selection for csv download
-    """
-    by_payment = forms.ChoiceField(choices=PC, required=False,
-        label=u'By payment')
-    by_amount = forms.MultipleChoiceField(choices=AC, required=False,
-        label=u'By amount')
-    by_party = forms.ChoiceField(choices=HC, required=False,
-        label=u'by party')
-    by_tshirt = forms.ChoiceField(choices=SC, required=False,
-        label=u'by tshirt size')
-    order_by = forms.ChoiceField(choices=OC, required=False,
-        label=u'order results')
-    include = forms.MultipleChoiceField(choices=IC, required=False,
-        label=u'Include fields')
--- a/project/kiwipycon/registration/labels.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-WIFI_CHOICES = (
-    ("0", "Yes"),
-    ('1', 'No'),
-    )
-
-WIFI_HELP = """Are you bringing a laptop to the event?"""
--- a/project/kiwipycon/registration/migrations/0001_initial.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from south.db import db
-from django.db import models
-from project.kiwipycon.registration.models import *
-
-class Migration:
-    
-    def forwards(self, orm):
-        
-        # Adding model 'Registration'
-        db.create_table('registration_registration', (
-            ('slug', models.SlugField()),
-            ('registrant', models.ForeignKey(orm['auth.User'])),
-            ('organisation', models.CharField(max_length=255, blank=True)),
-            ('occupation', models.CharField(max_length=255, blank=True)),
-            ('city', models.CharField(max_length=255, blank=True)),
-            ('postcode', models.CharField(max_length=255, blank=True)),
-            ('tshirt', models.CharField(max_length=2)),
-            ('conference', models.BooleanField(default=False)),
-            ('tutorial', models.BooleanField(default=False)),
-            ('sprint', models.BooleanField(default=False)),
-            ('submitted', models.DateTimeField(auto_now_add=True)),
-            ('allow_contact', models.BooleanField(default=False)),
-            ('last_mod', models.DateTimeField(auto_now=True)),
-            ('id', models.AutoField(primary_key=True)),            
-        ))
-        db.send_create_signal('registration', ['Registration'])
-        
-    
-    
-    def backwards(self, orm):
-        
-        # Deleting model 'Registration'
-        db.delete_table('registration_registration')
-        
-    
-    
-    models = {
-        'auth.user': {
-            '_stub': True,
-            'id': ('models.AutoField', [], {'primary_key': 'True'})
-        },
-        'registration.registration': {
-            'allow_contact': ('models.BooleanField', [], {'default': 'False'}),
-            'city': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'last_mod': ('models.DateTimeField', [], {'auto_now': 'True'}),
-            'occupation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'organisation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'conference': ('models.BooleanField', [], {'default': 'False'}),
-            'tutorial': ('models.BooleanField', [], {'default': 'False'}),
-            'sprint': ('models.BooleanField', [], {'default': 'False'}),
-            'postcode': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'registrant': ('models.ForeignKey', ['User'], {}),
-            'slug': ('models.SlugField', [], {}),
-            'submitted': ('models.DateTimeField', [], {'auto_now_add': 'True'}),
-            'tshirt': ('models.CharField', [], {'max_length': '2'})
-        }
-    }
-    
-    complete_apps = ['registration']
--- a/project/kiwipycon/registration/migrations/0002_create_wifi.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from south.db import db
-from django.db import models
-from project.kiwipycon.registration.models import *
-
-class Migration:
-    
-    def forwards(self, orm):
-        
-        # Adding model 'Wifi'
-        db.create_table('registration_wifi', (
-            ('wifi', models.CharField(max_length=50)),
-            ('user', models.ForeignKey(orm['auth.User'])),
-            ('id', models.AutoField(primary_key=True)),
-        ))
-        db.send_create_signal('registration', ['Wifi'])
-        
-    
-    
-    def backwards(self, orm):
-        
-        # Deleting model 'Wifi'
-        db.delete_table('registration_wifi')
-        
-    
-    
-    models = {
-        'auth.user': {
-            '_stub': True,
-            'id': ('models.AutoField', [], {'primary_key': 'True'})
-        },
-        'registration.wifi': {
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'user': ('models.ForeignKey', ['User'], {}),
-            'wifi': ('models.CharField', [], {'max_length': '50'})
-        },
-        'registration.registration': {
-            'allow_contact': ('models.BooleanField', [], {'default': 'False'}),
-            'city': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'last_mod': ('models.DateTimeField', [], {'auto_now': 'True'}),
-            'occupation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'organisation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'conference': ('models.BooleanField', [], {'default': 'False'}),
-            'tutorial': ('models.BooleanField', [], {'default': 'False'}),
-            'sprint': ('models.BooleanField', [], {'default': 'False'}),
-            'postcode': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'registrant': ('models.ForeignKey', ['User'], {}),
-            'slug': ('models.SlugField', [], {}),
-            'submitted': ('models.DateTimeField', [], {'auto_now_add': 'True'}),
-            'tshirt': ('models.CharField', [], {'max_length': '2'})
-        }
-    }
-    
-    complete_apps = ['registration']
--- a/project/kiwipycon/registration/models.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django.db import models
-from django.contrib.auth.models import User
-
-from .utils import send_confirmation_payment_email
-from .utils import send_banking_fix_email
-
-from .labels import WIFI_CHOICES
-from .labels import WIFI_HELP
-
-SIZE_CHOICES = (
-    ('S', 'S'),
-    ('M', 'M'),
-    ('L', 'L'),
-    ('XL', 'XL'),
-    )
-
-class Wifi(models.Model):
-    """Defines wifi options at *PyCon"""
-    user = models.ForeignKey(User)
-    wifi = models.CharField(max_length=50, choices=WIFI_CHOICES,
-            help_text=WIFI_HELP, verbose_name="Laptop")
-
-class Registration(models.Model):
-    """Defines registration at *PyCon"""
-    slug = models.SlugField()
-    registrant = models.ForeignKey(User)
-    organisation = models.CharField(max_length=255, blank=True)
-    occupation = models.CharField(max_length=255, blank=True)
-    city = models.CharField(max_length=255, blank=True)
-    postcode = models.CharField(max_length=255, blank=True)
-#    beverage = models.CharField(max_length=255, blank=True)
-#    diet = models.CharField(max_length=255, blank=True)
-#    sponsor = models.CharField(max_length=255, blank=True)
-    tshirt = models.CharField(max_length=2, choices=SIZE_CHOICES)
-#    party = models.BooleanField(default=False)
-#    discount = models.BooleanField(default=False)
-
-    # scipy.in specific
-    conference = models.BooleanField(default=False)
-    # scipy.in specific
-    tutorial = models.BooleanField(default=False)
-    # scipy.in specific
-    sprint = models.BooleanField(default=False)
-
-#    amount = models.IntegerField(default=0)
-    allow_contact = models.BooleanField(default=False)
-#    payment = models.BooleanField(default=False)
-    submitted = models.DateTimeField(auto_now_add=True)
-    last_mod = models.DateTimeField(auto_now=True)
-
-    def __unicode__(self):
-        return 'Registration for user: <%s %s> %s' % (self.registrant.first_name,
-                self.registrant.last_name, self.registrant.email)
-
-#    def save(self, *args, **kwargs):
-#        if(self.id):
-#            old_reg = Registration.objects.get(pk=self.id)
-#            if(old_reg.payment == False and self.payment == True \
-#                    and not self.sponsor):
-#                send_confirmation_payment_email(self.registrant)
-#            if(old_reg.slug.startswith('NZ') and self.slug.startswith('KPC') \
-#                    and not self.sponsor):
-#                send_banking_fix_email(self.registrant, self.slug)
-#        super(Registration, self).save(args, kwargs)
--- a/project/kiwipycon/registration/pdf.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-import os
-
-from django.conf import settings
-from django.template.loader import render_to_string
-
-def save_invoice(user, registration, template_name):
-    content = render_to_string(template_name,
-        {'registration' : registration, 'user': user})
-    filename = '%s.html' % registration.slug
-    filepath = os.path.join(settings.USER_MEDIA_PDF, filename)
-    save_to_file(content, filepath)
-
-def save_to_pdf(content, filepath):
-    import pisa
-    pisa.CreatePDF(str(content), file(filepath, 'wb'))
-
-def save_to_file(content, filepath):
-    fout = file(filepath, 'wb')
-    fout.write(content)
-    fout.close()
--- a/project/kiwipycon/registration/tests.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-
-
-def test_save_to_pdf():
-    """
-    >>> from .pdf import save_invoice
-    >>> from django.db.models.loading import get_model
-    >>> userModel =  get_model('auth', 'user')
-    >>> user = userModel(username='joe', email='joe@gmail.com',
-    ...         first_name='Joe', last_name='Bloggs')
-    >>> user.save()
-    >>> regModel =  get_model('registration', 'registration')
-    >>> registration = regModel(registrant=user, amount=40,
-    ...          slug='NZPYCON-0001')
-    >>> registration.save()
-
-    >>> save_invoice(user, registration, 'registration/invoice.html')
-
-    """
-    pass
--- a/project/kiwipycon/registration/utils.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-# django
-from django.core.mail import EmailMessage
-
-def send_confirmation(registrant, invoice, password=None, sponsor=None,
-        amount=None):
-
-    message = EmailMessage()
-    message.subject = u'Registration to SciPy.in 2009'
-    message.from_email = u'admin@scipy.in'
-    message.to = [registrant.email]
-    name = '%s %s' % (registrant.first_name, registrant.last_name)
-    if name.strip() == '':
-        name = registrant.username
-
-    username = registrant.username
-    all = {'name': name,
-            'password': password,
-            'username': username}
-
-    if password:
-        message.body = confirmation_newuser % all
-    else:
-        message.body = confirmation_currentuser % all
-
-    message.send()
-
-def send_confirmation_payment_email(registrant):
-    message = EmailMessage()
-    message.subject = u'Registration payment to SciPy.in 2009'
-    message.from_email = u'admin@scipy.in'
-    message.to = [registrant.email]
-    name = '%s %s' % (registrant.first_name, registrant.last_name)
-    username = registrant.username
-    if name.strip() == '':
-        name = registrant.username
-    message.body = confirmation_payment % dict(name=name,
-            username=username)
-    message.send()
-
-def send_banking_fix_email(registrant, invoicenum):
-    message = EmailMessage()
-    message.subject = u'Registration invoice update to SciPy.in 2009'
-    message.from_email = u'admin@scipy.in'
-    message.to = [registrant.email]
-    name = '%s %s' % (registrant.first_name, registrant.last_name)
-    username = registrant.username
-    if name.strip() == '':
-        name = registrant.username
-    message.body = banking_fix % dict(name=name,
-            username=username, invoice=invoicenum)
-    message.send()
-
-banking_fix = """
-Dear %(name)s,
-
-Invoice update to Kiwi Pycon 2009.
-
-Ooops. We made the invoice number too long to be entered for internet banking.
-We have therefore changed the prefix and your new invoice number is:
-%(invoice)s
-
-You will find that your online invoice has been updated. Thanks for your
-patience.
-
-http://nz.pycon.org/invoice
-A pdf version here:
-http://nz.pycon.org/pdf_invoice
-
-Regards,
-The Kiwi Pycon 2009 Team
-
-Your username, in case you've forgotten: %(username)s.
-
-If you have lost your password to the website please visit:
-http://nz.pycon.org/password-reset
-
-    """
-
-confirmation_payment = """
-Dear %(name)s,
-
-Welcome to Kiwi Pycon 2009.
-
-Your payment has been received and your attendence confirmed.
-
-Many thanks!
-
-You can view your invoice at:
-http://nz.pycon.org/invoice
-And a pdf version here:
-http://nz.pycon.org/pdf_invoice
-
-Regards,
-The Kiwi Pycon 2009 Team
-
-Your username, in case you've forgotten: %(username)s.
-
-If you have lost your password to the website please visit:
-http://nz.pycon.org/password-reset
-
-    """
-
-confirmation_newuser = """
-Dear %(name)s,
-
-Welcome to SciPy.in 2009. You may log in to 
-http://scipy.in/login using the following credentials:
-
-Username: %(username)s
-Password: %(password)s
-
-There is an entry fee for the SciPy conference only. However
-the sprint and tutorials don't have any entry fee. The entry
-fee for the conference can be paid on the spot on the first
-day of the conference.
-
-Thanks for your registration!
-
-Regards,
-The SciPy.in Team
-
-If you lose your password to the website please visit:
-http://scipy.in/password-reset
-    """
-
-confirmation_sponsoreduser = """
-Dear %(name)s,
-
-Welcome to Kiwi Pycon 2009.
-
-Your username is: %(username)s
-
-Your registration has been accepted as a guest of %(stype)s 
-sponsor %(sname)s.
-
-Thanks!
-
-Regards,
-The Kiwi Pycon 2009 Team
-
-If you have lost your password to the website please visit:
-http://nz.pycon.org/password-reset
-
-    """
-
-confirmation_sponsorednewuser = """
-Dear %(name)s,
-
-Welcome to Kiwi Pycon 2009.
-
-Your username is: %(username)s
-Your password is: %(password)s
-
-Your registration has been accepted as a guest of %(stype)s sponsor %(sname)s.
-
-Thanks!
-
-Regards,
-The Kiwi Pycon 2009 Team
-
-If you lose your password to the website please visit:
-http://nz.pycon.org/password-reset
-
-    """
-
-confirmation_currentuser = """
-Dear %(name)s,
-
-Welcome to SciPy.in 2009. You may log in to 
-http://scipy.in/login using the following credentials:
-
-Username: %(username)s
-Password: %(password)s
-
-There is an entry fee for the SciPy conference only. However
-the sprint and tutorials don't have any entry fee. The entry
-fee for the conference can be paid on the spot on the first
-day of the conference. 
-
-Thanks for your registration!
-
-Regards,
-The SciPy.in Team
-
-If you lose your password to the website please visit:
-http://scipy.in/password-reset
-    """
--- a/project/kiwipycon/registration/views.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,336 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-import cStringIO as StringIO
-import csv
-
-# django
-from django.conf import settings
-from django.shortcuts import render_to_response
-from django.template.loader import render_to_string
-from django.shortcuts import get_object_or_404
-from django.template import RequestContext
-from django.core.urlresolvers import reverse
-from django.http import HttpResponse
-
-from django.contrib.auth.decorators import login_required
-from django.contrib.auth.forms import AuthenticationForm
-from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
-
-#kiwipycon
-from project.kiwipycon.utils import set_message_cookie
-from project.kiwipycon.utils import slugify
-from project.kiwipycon.user.models import UserProfile
-from project.kiwipycon.user.utils import kiwipycon_createregistrant
-from project.kiwipycon.user.forms import RegistrantForm
-from project.kiwipycon.sponsor.models import Sponsor
-from project.kiwipycon.talk.models import Talk
-
-from .models import Registration
-from .models import Wifi
-from .forms import RegistrationSubmitForm
-from .forms import RegistrationEditForm
-from .forms import RegistrationAdminSelectForm
-from .forms import WifiForm
-from .utils import send_confirmation
-
-from .forms import IC
-
-REG_TOTAL = 1000
-
-@login_required
-def download_csv(request,
-        template_name = 'registration/download-csv.html'):
-    """
-    """
-    if not request.user.is_staff:
-        redirect_to = reverse('kiwipycon_login')
-    if request.method == "POST":
-        form = RegistrationAdminSelectForm(request.POST)
-        if form.is_valid():
-            conference = form.cleaned_data['by_conference']
-            tutorial = form.cleaned_data['by_tutorial']
-            sprint = form.cleaned_data['by_sprint']
-            amount = form.cleaned_data['by_amount']
-            tshirt = form.cleaned_data['by_tshirt']
-            order_by = form.cleaned_data['order_by']
-            include = form.cleaned_data['include']
-            q = Registration.objects.all()
-            if conference == 'conference':
-                q = q.filter(conference=True)
-            elif conference == 'no conference':
-                q = q.filter(conference=False)
-            elif tutorial == 'tutorial':
-                q = q.filter(tutorial=True)
-            elif tutorial == 'no tutorial':
-                q = q.filter(tutorial=False)
-            if sprint == 'sprint':
-                q = q.filter(sprint=True)
-            if sprint == 'no sprint':
-                q = q.filter(sprint=False)
-            elif tshirt != 'all':
-                q = q.filter(tshirt=tshirt)
-            q = q.order_by('registrant__email')
-            query = q.query
-            results = list(q)
-            if include == []:
-                # default to include all fields
-                include = [i[0] for i in IC]
-            if results:
-                response = HttpResponse(mimetype='text/csv')
-                response['Content-Disposition'] = 'attachment; filename=registrations.csv'
-                output = csv.writer(response)
-                output.writerow([h for h in include])
-                for row in results:
-                    conference = row.conference == True and 'yes' or 'no'
-                    tutorial = row.tutorial == True and 'yes' or 'no'
-                    sprint = row.sprint == True and 'yes' or 'no'
-                    wrow = []
-                    if 'Name' in include:
-                        wrow.append(
-                            row.registrant.get_full_name().encode('utf-8'))
-                    if 'Email' in include:
-                        wrow.append(row.registrant.email.encode('utf-8'))
-                    if 'Organisation' in include:
-                        wrow.append(row.organisation.encode('utf-8'))
-                    if 'Conference' in include:
-                        wrow.append(conference)
-                    if 'Tutorial' in include:
-                        wrow.append(tutorial)
-                    if 'Sprint' in include:
-                        wrow.append(sprint)
-                    if 'T-size' in include:
-                        wrow.append(row.tshirt)
-                    output.writerow(wrow)
-                return response
-            else:
-                no_results = u'No results found for the query'
-
-    else:
-        form = RegistrationAdminSelectForm()
-    return render_to_response(template_name, RequestContext(request,
-        locals()))
-
-# NOT REQUIRED FOR SciPy.in
-@login_required
-def invoice(request, template_name='registration/invoice.html'):
-    user = request.user
-    registration = get_object_or_404(Registration, registrant=user)
-    if registration.sponsor:
-        redirect_to = reverse('kiwipycon_account')
-        return set_message_cookie(redirect_to,
-                msg = u'You are a sponsored guest, no payment required.')
-    return render_to_response(template_name, RequestContext(request,
-        {'registration' : registration, 'user': user}))
-
-@login_required
-def pdf_invoice(request, template_name='registration/invoice.html'):
-    user = request.user
-    registration = get_object_or_404(Registration, registrant=user)
-    if registration.sponsor:
-        redirect_to = reverse('kiwipycon_account')
-        return set_message_cookie(redirect_to,
-                msg = u'You are a sponsored guest, no payment required.')
-    content = render_to_string(template_name,
-        {'registration' : registration, 'user': user})
-    result = StringIO.StringIO()
-    import ho.pisa
-    pdf = ho.pisa.pisaDocument(StringIO.StringIO(content.encode("UTF-8")),result)
-    if not pdf.err:
-        return HttpResponse(result.getvalue(), mimetype='application/pdf')
-    return HttpResponse("Gremlins ate your invoice, please try html" \
-        " version")
-
-
-def registrations(request,
-        template_name='registration/registrations.html'):
-    """Simple page to count registrations"""
-    #registrations = Registration.objects.filter(payment=True).count()
-    registrations = Registration.objects.all().count()
-    return render_to_response(template_name, RequestContext(request,
-        {
-        'over_reg' : registrations >= REG_TOTAL and True or False,
-            'registrations' : registrations}))
-
-@login_required
-def edit_registration(request, id,
-        template_name='registration/edit-registration.html'):
-    '''Allows users that submitted a registration to edit it.
-    '''
-    reg = Registration.objects.get(pk=id)
-
-    if reg.registrant != request.user:
-        redirect_to = reverse('kiwipycon_account')
-        return set_message_cookie(redirect_to,
-                msg = u'Redirected because the registration you selected' \
-                      + ' is not your own.')
-
-    if request.method == 'POST':
-        form = RegistrationEditForm(data=request.POST)
-        if form.is_valid():
-            reg.organisation = form.data.get('organisation')
-            reg.occupation = form.data.get('occupation')
-            reg.city = form.data.get('city')
-            reg.tshirt = form.data.get('tshirt')
-            reg.allow_contact = form.data.get('allow_contact') and True or False
-            reg.conference = form.data.get('conference') and True or False
-            reg.tutorial = form.data.get('tutorial') and True or False
-            reg.sprint = form.data.get('sprint') and True or False
-            reg.save()
-            # Saved.. redirect
-            redirect_to = reverse('kiwipycon_account')
-            return set_message_cookie(redirect_to,
-                    msg = u'Your changes have been saved.')
-    else:
-        form = RegistrationEditForm(initial={
-                                    'id' : id,
-                                    'organisation' : reg.organisation,
-                                    'occupation' : reg.occupation,
-                                    'city' : reg.city,
-                                    'tshirt' : reg.tshirt,
-                                    'conference': reg.conference,
-                                    'tutorial': reg.tutorial,
-                                    'postcode' : reg.postcode,
-                                    'sprint' : reg.sprint,
-                                    'allow_contact' : reg.allow_contact,
-            })
-
-    return render_to_response(template_name, RequestContext(request, locals()))
-
-def submit_registration(request,
-        template_name='registration/submit-registration.html'):
-    '''Allows user to edit registration
-    '''
-    user = request.user
-    reg_count = Registration.objects.all().count()
-    if user.is_authenticated():
-        try:
-            profile = user.get_profile()
-        except:
-            profile, new = UserProfile.objects.get_or_create(user=user)
-            if new:
-                profile.save()
-        try:
-            registration = Registration.objects.get(registrant=user)
-            if registration:
-                redirect_to = reverse('kiwipycon_account')
-                return set_message_cookie(redirect_to,
-                        msg = u'You have already been registered.')
-
-        except ObjectDoesNotExist:
-            pass
-
-    message = None
-
-    if request.method == 'POST':
-        registration_form = RegistrationSubmitForm(data=request.POST)
-        registrant_form = RegistrantForm(data=request.POST)
-        wifi_form = WifiForm(data=request.POST)
-
-        if request.POST.get('action', None) == 'login':
-            login_form = AuthenticationForm(data=request.POST)
-            if login_form.is_valid():
-
-                from django.contrib.auth import login
-                login(request, login_form.get_user())
-
-                redirect_to = reverse('kiwipycon_submit_registration')
-                return set_message_cookie(redirect_to,
-                        msg = u'You have been logged in please continue' + \
-                               'with registration.')
-
-        newuser = None
-        passwd = None
-        if not user.is_authenticated():
-            if registrant_form.is_valid():
-                newuser = kiwipycon_createregistrant(request, registrant_form.data)
-                # Log in user
-                passwd = User.objects.make_random_password()
-                newuser.set_password(passwd)
-                newuser.save()
-                from django.contrib.auth import authenticate
-                user = authenticate(username=newuser.username, password=passwd)
-
-                from django.contrib.auth import login
-                login(request, user)
-
-                newuser = user
-
-        else:
-            newuser = user
-
-        if registration_form.is_valid() and newuser:
-            allow_contact = registration_form.data.get('allow_contact') and \
-                                        True or False
-            conference = registration_form.data.get('conference') and \
-                                        True or False
-            tutorial = registration_form.data.get('tutorial') and \
-                                        True or False
-            sprint = registration_form.data.get('sprint') and \
-                                        True or False
-
-            registrant = User.objects.get(pk=newuser.id)
-
-            presenter = None
-            talks = Talk.objects.filter(
-                    speaker=registrant).filter(approved=True)
-            if talks:
-                for talk in talks:
-                    if talk.duration == '30':
-                        presenter = True
-                    elif talk.duration == '60':
-                        presenter = True
-            
-            reg = Registration(
-                    #     slug = newuser.username,
-                registrant = registrant,
-                organisation = registration_form.data.get('organisation'),
-                occupation = registration_form.data.get('occupation'),
-                city = registration_form.data.get('city'),
-                tshirt = registration_form.data.get('tshirt'),
-                postcode = registration_form.cleaned_data.get('postcode'),
-                allow_contact = allow_contact,
-                conference = conference,
-                tutorial = tutorial,
-                sprint = sprint)
-            reg.save() 
-
-            # get id and use as slug and invoice number
-            id = reg.id
-            slug = 'KPC09%03d' % id
-            reg.slug = slug
-            reg.save()
-
-            # additional tasks:
-            if wifi_form.is_valid():
-                wifi = wifi_form.save(registrant)
-            
-            # 1. include random password if we are a new user
-            if passwd:
-                send_confirmation(registrant, slug, password=passwd)
-            else:
-            # 2. send user email with registration id
-                send_confirmation(registrant, slug)
-
-            redirect_to = reverse('kiwipycon_registrations')
-            return set_message_cookie(redirect_to,
-                    msg = u'Thank you, your registration has been submitted '\
-                           'and an email has been sent with payment details.')
-
-    else:
-        registration_form = RegistrationSubmitForm()
-        registrant_form = RegistrantForm()
-        wifi_form = WifiForm()
-
-    login_form = AuthenticationForm()
-
-
-    return render_to_response(template_name, RequestContext(request, {
-        'registration_form': registration_form,
-        'registrant_form' : registrant_form,
-        'over_reg' : reg_count >= REG_TOTAL and True or False,
-        'wifi_form' : wifi_form,
-        'message' : message,
-        'login_form' : login_form
-    }))
--- a/project/kiwipycon/sponsor/admin.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django.contrib import admin
-
-#kiwipycon
-from .models import Sponsor
-
-class SponsorAdmin(admin.ModelAdmin):
-    list_display = ('title', 'type', 'contact_name', 'contact_email', 'contact_phone',
-            'guests', 'url', 'logo')
-
-admin.site.register(Sponsor, SponsorAdmin)
-
--- a/project/kiwipycon/sponsor/migrations/0001_initial.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from south.db import db
-from django.db import models
-from project.kiwipycon.sponsor.models import *
-
-class Migration:
-    
-    def forwards(self, orm):
-        
-        # Adding model 'Sponsor'
-        db.create_table('sponsor_sponsor', (
-            ('id', models.AutoField(primary_key=True)),
-            ('slug', models.SlugField()),
-            ('title', models.CharField(max_length=255)),
-            ('type', models.CharField(max_length=10)),
-            ('url', models.URLField(verify_exists=False, blank=True)),
-            ('contact_name', models.CharField(max_length=255)),
-            ('contact_phone', models.CharField(max_length=255)),
-            ('contact_email', models.CharField(max_length=255)),
-            ('logo', models.CharField(max_length=64, blank=True)),
-            ('guests', models.IntegerField()),
-        ))
-        db.send_create_signal('sponsor', ['Sponsor'])
-        
-    
-    
-    def backwards(self, orm):
-        
-        # Deleting model 'Sponsor'
-        db.delete_table('sponsor_sponsor')
-        
-    
-    
-    models = {
-        'sponsor.sponsor': {
-            'contact_email': ('models.CharField', [], {'max_length': '255'}),
-            'contact_name': ('models.CharField', [], {'max_length': '255'}),
-            'contact_phone': ('models.CharField', [], {'max_length': '255'}),
-            'guests': ('models.IntegerField', [], {}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'logo': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}),
-            'slug': ('models.SlugField', [], {}),
-            'title': ('models.CharField', [], {'max_length': '255'}),
-            'type': ('models.CharField', [], {'max_length': '10'}),
-            'url': ('models.URLField', [], {'verify_exists': 'False', 'blank': 'True'})
-        }
-    }
-    
-    complete_apps = ['sponsor']
--- a/project/kiwipycon/sponsor/models.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django.db import models
-from django.conf import settings
-
-TYPE_CHOICES = (
-    ('gold', 'Gold'),
-    ('silver', 'Silver'),
-    ('schwag', 'Schwag'),
-    )
-
-class Sponsor(models.Model):
-    """Defines sponsors for *PyCon"""
-    slug = models.SlugField()
-    title = models.CharField(max_length=255)
-    type = models.CharField(max_length=10, choices=TYPE_CHOICES)
-    contact_name = models.CharField(max_length=255)
-    contact_email = models.CharField(max_length=255)
-    contact_phone = models.CharField(max_length=255)
-    url = models.URLField(blank=True, verify_exists=False)
-    logo = models.CharField(max_length=64, blank=True)
-    guests = models.IntegerField()
-
-    def __unicode__(self):
-        return self.title
-
--- a/project/kiwipycon/sponsor/views.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-# django
-from django.conf import settings
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-
-def schwag_sponsors(request,
-        template_name = 'sponsor/schwag.html'):
-    """Simple page to display schwag sponsors
-    
-    The list is generated in kiwipycon.context_processors
-    """
-    return render_to_response(template_name, RequestContext(request,
-        {}))
-
--- a/project/kiwipycon/talk/admin.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django.contrib
-from django.contrib import admin
-
-#kiwipycon
-from .models import Talk
-
-class TalkAdmin(admin.ModelAdmin):
-    list_display = ('title', 'speaker', 'topic', 'duration', 'audience', 'approved')
-    list_filter = ('approved', 'audience', 'topic', 'speaker')
-    search_fields = ('slug', 'title', 'abstract')
-    prepopulate_from = {'slug': ('title',)}
-    fieldsets = (
-        ('Details', {
-            'fields': ('slug', 'title', 'abstract', 'speaker')
-        }),
-        ('Information', {
-            'fields': ('topic', 'duration', 'audience', 'approved')
-        }),
-    )
-admin.site.register(Talk, TalkAdmin)
--- a/project/kiwipycon/talk/forms.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django import forms
-
-#django.contrib
-from django.contrib.auth.models import User
-
-#tagging
-from tagging.forms import TagField
-
-#kiwipycon
-#from .models import TOPIC_CHOICES
-from .models import DURATION_CHOICES
-from .models import AUDIENCE_CHOICES
-
-
-class TalkSubmitForm(forms.Form):
-    """Submit talk form
-    """
-    authors_bio = forms.CharField(widget=forms.Textarea, required=True,
-        label=u'Author(s) and short bio',
-        help_text=u'(include a bit about your qualifications regarding your presentation topic)')
-    contact = forms.EmailField(required=True, label=u'E-Mail ID',
-        help_text=u'Provide your email ID',
-        max_length=1024,
-        widget=forms.TextInput(attrs={'size':'50'}))
-    title = forms.CharField(required=True, label=u'Talk title',
-        help_text=u'Title of proposed presentation',
-        max_length=1024,
-        widget=forms.TextInput(attrs={'size':'50'}))
-    abstract = forms.CharField(widget=forms.Textarea, required=True,
-        help_text=u'Summary of proposed presentation (In 300-700 words)')
-#    outline = forms.CharField(widget=forms.Textarea, required=True,
-#        help_text=u'Outline of proposed presentation (around 200 words)')
-#    topic = forms.ChoiceField(choices=TOPIC_CHOICES,
-#        label=u'Topic', help_text=u'Select one of the available options or enter other topic')
-#    topic_other = forms.CharField(label=u'Other topic',
-#        help_text=u'Description of your topic',
-#        max_length=255,
-#        required=False,
-#        widget=forms.TextInput(attrs={'size':'50'}))
-    topic = forms.CharField(label=u'Topic',
-        help_text=u'Description of your topic or comma separated tags',
-        max_length=255,
-        required=False,
-        widget=forms.TextInput(attrs={'size':'50'}))
-    duration = forms.ChoiceField(choices=DURATION_CHOICES, required=True,
-        label=u'Preferred timeslot', help_text=u'Select preferred time slot')
-    audience = forms.ChoiceField(choices=AUDIENCE_CHOICES, label=u'Intended audience',
-        help_text=u'Select one of the available options or enter other type of intended audience')
-#    audience_other = forms.CharField(label=u'Other intended audience',
-#        help_text=u'Description of intended audience (ie. Discordians)',
-#        max_length=128,
-#        required=False,
-#        widget=forms.TextInput(attrs={'size':'50'}))
-#    tags = TagField(max_length=255,
-#        widget=forms.TextInput(attrs={'size':'50'}))
-
-class TalkEditForm(TalkSubmitForm):
-    id = forms.CharField(widget=forms.HiddenInput)
--- a/project/kiwipycon/talk/migrations/0001_initial.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from south.db import db
-from django.db import models
-from project.kiwipycon.talk.models import *
-
-class Migration:
-    
-    def forwards(self, orm):
-        
-        # Adding model 'Talk'
-        db.create_table('talk_talk', (
-            ('id', models.AutoField(primary_key=True)),
-            ('slug', models.SlugField()),
-            ('speaker', models.ForeignKey(orm['auth.User'])),
-            ('authors_bio', models.TextField()),
-            ('contact', models.CharField(max_length=1024)),
-            ('title', models.CharField(max_length=1024)),
-            ('abstract', models.TextField()),
-#            ('outline', models.TextField()),
-            ('topic', models.CharField(blank=True, max_length=255)),
-#            ('topic_other', models.CharField(max_length=255, blank=True)),
-            ('duration', models.CharField(max_length=3)),
-            ('audience', models.CharField(blank=True, max_length=32)),
-#            ('audience_other', models.CharField(max_length=128, blank=True)),
-            ('approved', models.BooleanField(default=False)),
-            ('submitted', models.DateTimeField(auto_now_add=True)),
-            ('last_mod', models.DateTimeField(auto_now=True)),
-#            ('tags', TagField(blank=True)),
-        ))
-        db.send_create_signal('talk', ['Talk'])
-        
-    
-    
-    def backwards(self, orm):
-        
-        # Deleting model 'Talk'
-        db.delete_table('talk_talk')
-        
-    
-    
-    models = {
-        'auth.user': {
-            '_stub': True,
-            'id': ('models.AutoField', [], {'primary_key': 'True'})
-        },
-        'talk.talk': {
-            'abstract': ('models.TextField', [], {}),
-            'approved': ('models.BooleanField', [], {'default': 'False'}),
-            'audience': ('models.CharField', [], {'blank': 'True', 'max_length': '32'}),
-            'audience_other': ('models.CharField', [], {'max_length': '128', 'blank': 'True'}),
-            'authors_bio': ('models.TextField', [], {}),
-            'contact': ('models.CharField', [], {'max_length': '1024'}),
-            'duration': ('models.CharField', [], {'max_length': '3'}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'last_mod': ('models.DateTimeField', [], {'auto_now': 'True'}),
-            'outline': ('models.TextField', [], {}),
-            'slug': ('models.SlugField', [], {}),
-            'speaker': ('models.ForeignKey', ['User'], {}),
-            'submitted': ('models.DateTimeField', [], {'auto_now_add': 'True'}),
-            'tags': ('TagField', [], {'blank': 'True'}),
-            'title': ('models.CharField', [], {'max_length': '1024'}),
-            'topic': ('models.CharField', [], {'blank': 'True', 'max_length': '255'}),
-            'topic_other': ('models.CharField', [], {'max_length': '255', 'blank': 'True'})
-        }
-    }
-    
-    complete_apps = ['talk']
--- a/project/kiwipycon/talk/models.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django.db import models
-from django.contrib.auth.models import User
-
-#tagging
-from tagging import register
-from tagging.fields import TagField
-from tagging.utils import parse_tag_input
-
-DURATION_CHOICES = (
-    ('10', 'Lightning Talk (10 mins)'),
-    ('20', 'Short Talk (20 mins)'),
-    ('30', 'Standard Talk (30 mins)'),
-    )
-
-AUDIENCE_CHOICES = (
-    ('nonprogrammers', 'non-programmer'),
-    ('beginers', 'beginning programmer'),
-    ('intermediate', 'intermediate programmer'),
-    ('advanced', 'advanced programmer'),
-    )
-
-#TOPIC_CHOICES = (
-#    ('Core Python', 'Core Python'),
-#    ('Other implementations: Jython, IronPython, PyPy, and Stackless', 'Other implementations: Jython, IronPython, PyPy, and Stackless'),
-#    ('Python libraries and extensions', 'Python libraries and extensions'),
-#    ('Python 3k', 'Python 3k'),
-#    ('Databases', 'Databases'),
-#    ('Documentation', 'Documentation'),
-#    ('GUI Programming', 'GUI Programming'),
-#    ('Game Programming', 'Game Programming'),
-#    ('Network Programming', 'Network Programming'),
-#    ('Open Source Python projects', 'Open Source Python projects'),
-#    ('Packaging Issues', 'Packaging Issues'),
-#    ('Programming Tools', 'Programming Tools'),
-#    ('Project Best Practices', 'Project Best Practices'),
-#    ('Embedding and Extending', 'Embedding and Extending'),
-#    ('Science and Maths', 'Science and Maths'),
-#    ('Web-based Systems', 'Web-based Systems'),
-#)
-
-class Talk(models.Model):
-    """Defines talks at *PyCon"""
-    slug = models.SlugField()
-    speaker = models.ForeignKey(User)
-    authors_bio = models.TextField()
-    contact = models.EmailField()
-    title = models.CharField(max_length=1024)
-    abstract = models.TextField()
-#    outline = models.TextField()
-    topic = models.CharField(max_length=255, 
-                             #choices=TOPIC_CHOICES,
-                             blank=True)
-#    topic_other = models.CharField(max_length=255, blank=True)
-    duration = models.CharField(max_length=3, choices=DURATION_CHOICES)
-    audience = models.CharField(max_length=32, choices=AUDIENCE_CHOICES, blank=True)
-#    audience_other = models.CharField(max_length=128, blank=True)
-    approved = models.BooleanField(default=False)
-    submitted = models.DateTimeField(auto_now_add=True)
-    last_mod = models.DateTimeField(auto_now=True)
-#    tags = TagField(blank=True)
-
-    def __unicode__(self):
-        return self.title
-
-    def get_tag_list(self):
-        return parse_tag_input(self.tags)
-
-# register(Talk) # saving talk failed - see:
-# http://code.google.com/p/django-tagging/issues/detail?id=152
--- a/project/kiwipycon/talk/templatetags/__init__.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-#
--- a/project/kiwipycon/talk/templatetags/talk_extras.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-from django import template
-
-register = template.Library()
-
-def choice(choices, value):
-    return choices[value]
-
-register.filter('choice', choice)
--- a/project/kiwipycon/talk/views.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-# python imports
-from urlparse import urlparse
-
-# django
-from django.conf import settings
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.core.urlresolvers import reverse
-from django.views.generic.list_detail import object_list
-from django.views.generic.list_detail import object_detail
-
-from django.contrib.auth.decorators import login_required
-from django.contrib.auth.forms import AuthenticationForm
-from django.contrib.auth.models import User
-
-# PIL
-from PIL import Image
-
-# tagging
-from tagging.models import Tag
-
-#kiwipycon
-from project.kiwipycon.utils import set_message_cookie
-from project.kiwipycon.utils import slugify
-from project.kiwipycon.user.models import UserProfile
-from project.kiwipycon.user.forms import RegisterForm
-from project.kiwipycon.user.utils import kiwipycon_createuser
-
-from .models import Talk
-from .forms import TalkSubmitForm
-from .forms import TalkEditForm
-from .models import DURATION_CHOICES
-from .models import AUDIENCE_CHOICES
-
-def list_talks(request):
-    objects = Talk.objects.filter(approved=True)
-    extra_context = dict(count=objects.count())
-    return object_list(request, objects, extra_context=extra_context)
-
-def talk(request, id):
-    objects = Talk.objects.filter(approved=True)
-    audience = {}
-    for choice in AUDIENCE_CHOICES:
-        audience[choice[0]] = choice[1]
-    extra_context = dict(choices=audience)
-    return object_detail(request, objects, id, extra_context=extra_context)
-
-@login_required
-def edit_talk(request, id, template_name='talk/edit-talk.html'):
-    '''Allows users that submitted a talk to edit it until the talk is approved.
-    '''
-    talk = Talk.objects.get(pk=id)
-
-    if talk.approved == True:
-        redirect_to = reverse('kiwipycon_account')
-        return set_message_cookie(redirect_to,
-                msg = u'Sorry but you cannot edit the talk once'\
-                      + ' it has been accepted.')
-    if talk.speaker != request.user:
-        redirect_to = reverse('kiwipycon_account')
-        return set_message_cookie(redirect_to,
-                msg = u'Redirected to account because the talk you selected' \
-                      + ' is not your own.')
-
-    if request.method == 'POST':
-        form = TalkEditForm(data=request.POST)
-        if form.is_valid():
-            talk.slug = slugify(form.data.get('title'))
-            talk.authors_bio = form.data.get('authors_bio')
-            talk.contact = form.data.get('contact')
-            talk.title = form.data.get('title')
-            talk.abstract = form.data.get('abstract')
-#            talk.outline = form.data.get('outline')
-            talk.topic = form.data.get('topic')
-#            talk.topic_other = form.data.get('topic_other')
-            talk.duration = form.data.get('duration')
-            talk.audience = form.data.get('audience')
-#            talk.audience_other = form.data.get('audience_other')
-#            talk.tags = form.data.get('tags')
-            talk.save()
-            # Saved.. redirect
-            redirect_to = reverse('kiwipycon_account')
-            return set_message_cookie(redirect_to,
-                    msg = u'Your changes have been saved.')
-    else:
-        form = TalkEditForm(initial={
-                                    'id' : id,
-                                    'authors_bio' : talk.authors_bio,
-                                    'contact' : talk.contact,
-                                    'title' : talk.title,
-                                    'abstract' : talk.abstract,
-#                                    'outline' : talk.outline,
-                                    'topic' : talk.topic,
-#                                    'topic_other' : talk.topic_other,
-                                    'duration' : talk.duration,
-                                    'audience' : talk.audience,
-#                                    'audience_other' : talk.audience_other,
-#                                    'tags' : talk.tags,
-            })
-
-    return render_to_response(template_name, RequestContext(request, locals()))
-
-@login_required()
-def submit_talk(request, template_name='talk/submit-talk.html'):
-    '''Allows user to edit profile
-    '''
-    user = request.user
-    if user.is_authenticated():
-        try:
-            profile = user.get_profile()
-        except:
-            profile, new = UserProfile.objects.get_or_create(user=user)
-            if new:
-                profile.save()
-    message = None
-
-    if request.method == 'POST':
-        talk_form = TalkSubmitForm(data=request.POST)
-
-        register_form = RegisterForm(data=request.POST,
-                                        files=request.FILES)
-
-        if request.POST.get('action', None) == 'login':
-            login_form = AuthenticationForm(data=request.POST)
-            if login_form.is_valid():
-
-                from django.contrib.auth import login
-                login(request, login_form.get_user())
-
-                redirect_to = reverse('kiwipycon_submit_talk')
-                return set_message_cookie(redirect_to,
-                        msg = u'You have been logged in.')
-
-        if request.POST.get('action', None) == 'register':
-            # add the new user
-            if register_form.is_valid():
-
-                user = kiwipycon_createuser(request, register_form.data)
-
-        if talk_form.is_valid():
-            if user.is_authenticated():
-                title = talk_form.data.get('title')
-                talk = Talk.objects.create(
-                    slug = slugify(title),
-                    speaker = User.objects.get(pk=user.id),
-                    authors_bio = talk_form.data.get('authors_bio'),
-                    contact = talk_form.data.get('contact'),
-                    title = talk_form.data.get('title'),
-                    abstract = talk_form.data.get('abstract'),
-#                    outline = talk_form.data.get('outline'),
-                    topic = talk_form.data.get('topic'),
-#                    topic_other = talk_form.data.get('topic_other'),
-                    duration = talk_form.data.get('duration'),
-                    audience = talk_form.data.get('audience'),
-#                    audience_other = talk_form.data.get('audience_other'),
-                    approved = False,
-#                    tags = talk_form.data.get('tags')
-                    )
-                talk.save()
-                # Saved, ... redirect back to account
-                redirect_to = reverse('kiwipycon_account')
-                return set_message_cookie(redirect_to,
-                        msg = u'Thanks, your talk has been submitted.')
-            else:
-                redirect_to = reverse('kiwipycon_submit_talk')
-                return set_message_cookie(redirect_to,
-                        msg = u'Something is wrong here.')
-
-    else:
-        talk_form = TalkSubmitForm()
-        register_form = RegisterForm()
-    login_form = AuthenticationForm()
-
-
-    return render_to_response(template_name, RequestContext(request, {
-        'talk_form': talk_form,
-        'register_form' : register_form,
-        'message' : message,
-        'login_form' : login_form
-    }))
-
-def list_talks(request, template_name='talk/list-all-talks.html'):
-    '''List all the tasks submitted by a user.
-    '''
-
-    talks = Talk.objects.filter(approved=True)
-
-    return render_to_response(template_name, RequestContext(request, {
-        'talk_list': talks,
-    }))
--- a/project/kiwipycon/user/admin.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django.contrib import admin
-
-#kiwipycon
-from .models import UserProfile
-
-class UserProfileAdmin(admin.ModelAdmin):
-    list_display = ('user', 'email',  'url', 'about')
-
-    def email(self, obj):
-        return obj.user.email
-
-admin.site.register(UserProfile, UserProfileAdmin)
-
--- a/project/kiwipycon/user/forms.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django import forms
-from django.contrib.auth.models import User
-
-class RegistrantForm(forms.Form):
-    """Form to register an attendee
-    """
-    username = forms.RegexField(label="Nickname", max_length=30,
-            regex=r'^\w+$',
-        help_text = "30 characters or fewer. Alphanumeric" \
-            + " characters only (letters, digits and underscores).",
-        error_message = "This value must contain only letters, numbers and underscores.")
-    name = forms.CharField(label=u"Name", max_length=50, required=True)
-    email = forms.EmailField(label=u"E-mail", max_length=50, required=True)
-
-    def clean_email(self):
-        """Validates that the entered e-mail is unique.
-        """
-        email = self.cleaned_data.get("email")
-        if email and User.objects.filter(email=email).count() > 0:
-            raise forms.ValidationError(
-                u"That email address is already in use. Are you a member of " \
-                 "site? Please log in.")
-
-        return email
-
-    def clean_username(self):
-        """Validates that the entered username is unique.
-        """
-        username = self.cleaned_data.get("username")
-        if username and User.objects.filter(username=username).count() > 0:
-            raise forms.ValidationError(
-                u"That username is already in use.")
-
-        return username
-
-class RegisterForm(forms.Form):
-    """Form to register speaker
-    """
-    username = forms.RegexField(label="Username", max_length=30,
-            regex=r'^\w+$',
-        help_text = "Required. 30 characters or fewer. Alphanumeric" \
-            + " characters only (letters, digits and underscores).",
-        error_message = "This value must contain only letters, numbers and underscores.")
-    first_name = forms.CharField(label=u"First name", max_length=50)
-    last_name = forms.CharField(label=u"Last name", max_length=50)
-    email = forms.EmailField(label=u"E-mail", max_length=50)
-    url = forms.URLField(required=False)
-    about = forms.CharField(label=u'Short Bio', max_length=50, required=False)
-    photo = forms.FileField(label=u'Profile Photo', required=False)
-    password_1 = forms.CharField(
-        label=u"Password", widget=forms.PasswordInput(), max_length=20)
-    password_2 = forms.CharField(
-        label=u"Confirm password", widget=forms.PasswordInput(), max_length=20)
-
-    def clean_password_2(self):
-        """Validates that password 1 and password 2 are the same.
-        """
-        p1 = self.cleaned_data.get('password_1')
-        p2 = self.cleaned_data.get('password_2')
-
-        if not (p1 and p2 and p1 == p2):
-            raise forms.ValidationError(u"The two passwords do not match.")
-
-        return p2
-
-    def clean_email(self):
-        """Validates that the entered e-mail is unique.
-        """
-        email = self.cleaned_data.get("email")
-        if email and User.objects.filter(email=email).count() > 0:
-            raise forms.ValidationError(
-                u"That email address is already in use.")
-
-        return email
-
-    def clean_username(self):
-        """Validates that the entered username is unique.
-        """
-        username = self.cleaned_data.get("username")
-        if username and User.objects.filter(username=username).count() > 0:
-            raise forms.ValidationError(
-                u"That username is already in use.")
-
-        return username
-
-class EditProfileForm(forms.Form):
-    """Edit user profile form
-    """
-    first_name = forms.CharField(max_length=50)
-    last_name = forms.CharField(max_length=50)
-    email = forms.EmailField(max_length=50)
-    email2 = forms.CharField(widget=forms.HiddenInput)
-    url = forms.URLField(required=False)
-    about = forms.CharField(label=u'Short Bio',
-            widget=forms.Textarea, required=False)
-    photo = forms.FileField(label=u'Profile Photo',
-            required=False)
-
-    def clean_email(self):
-        """Validates that the entered e-mail is unique.
-        """
-        email = self.cleaned_data.get("email")
-        email2 = self.data.get("email2").strip()
-        print email, email2
-        if email != email2: # email has been changed
-            if email and User.objects.filter(email=email).count() > 0:
-                raise forms.ValidationError(
-                    u"That email address is already in use.")
-
-        return email
-
-class UsernameForm(forms.Form):
-    """Form to edit email address
-    """
-    username = forms.RegexField(label="Username", max_length=30,
-            regex=r'^\w+$',
-        help_text = "Required. 30 characters or fewer. Alphanumeric" \
-            + " characters only (letters, digits and underscores).",
-        error_message = "This value must contain only letters, numbers and underscores.")
-
-    def clean_username(self):
-        """Validates that the entered username is unique.
-        """
-        username = self.cleaned_data.get("username")
-        if username and User.objects.filter(username=username).count() > 0:
-            raise forms.ValidationError(
-                u"That username is already in use.")
-
-        return username
-
-
--- a/project/kiwipycon/user/migrations/0001_initial.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from south.db import db
-from django.db import models
-from project.kiwipycon.user.models import *
-
-class Migration:
-    
-    def forwards(self, orm):
-        
-        # Adding model 'UserProfile'
-        db.create_table('user_userprofile', (
-            ('id', models.AutoField(primary_key=True)),
-            ('user', models.ForeignKey(orm['auth.User'], unique=True)),
-            ('url', models.URLField(verify_exists=False, blank=True)),
-            ('photo', models.CharField(max_length=64, blank=True)),
-            ('about', models.TextField(blank=True)),
-        ))
-        db.send_create_signal('user', ['UserProfile'])
-        
-    
-    
-    def backwards(self, orm):
-        
-        # Deleting model 'UserProfile'
-        db.delete_table('user_userprofile')
-        
-    
-    
-    models = {
-        'auth.user': {
-            '_stub': True,
-            'id': ('models.AutoField', [], {'primary_key': 'True'})
-        },
-        'user.userprofile': {
-            'about': ('models.TextField', [], {'blank': 'True'}),
-            'id': ('models.AutoField', [], {'primary_key': 'True'}),
-            'photo': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}),
-            'url': ('models.URLField', [], {'verify_exists': 'False', 'blank': 'True'}),
-            'user': ('models.ForeignKey', ['User'], {'unique': 'True'})
-        }
-    }
-    
-    complete_apps = ['user']
--- a/project/kiwipycon/user/models.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#django
-from django.db import models
-from django.conf import settings
-from django.db.models.signals import post_save
-from django.contrib.auth.models import User
-
-class UserProfile(models.Model):
-    """
-    Extend atributes for django User
-    """
-    user = models.ForeignKey(User, unique=True)
-    url = models.URLField(blank=True, verify_exists=False)
-    photo = models.CharField(max_length=64, blank=True)
-    about = models.TextField(blank=True)
-
-    def __unicode__(self):
-        return 'UserProfile for user: <%s %s> %s' % (self.user.first_name,
-                self.user.last_name, self.user.email)
-
-    def fullname(self):
-        return '%s %s' % (self.user.first_name, self.user.last_name)
-
-def add_profile(sender, instance, signal, *args, **kwargs):
-    """Create user profile on create of new user"""
-    if not instance.is_superuser:
-        try:
-            profile, new = UserProfile.objects.get_or_create(user=instance)
-            if new:
-                profile.save()
-        except:
-            pass
-
-post_save.connect(add_profile, sender=User, weak=False)
--- a/project/kiwipycon/user/utils.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#python imports
-import os
-
-#django
-from django.conf import settings
-from django.core.exceptions import ObjectDoesNotExist
-
-#django.contrib
-from django.contrib.auth.models import User
-
-#PIL
-from PIL import Image
-
-
-def kiwipycon_createregistrant(request, data):
-    """Create user"""
-    email = data.get("email")
-    name = data.get("name")
-    username = data.get("username")
-
-    n = name.split(" ")
-    if len(n) > 1:
-        first_name = ' '.join(n[:-1])
-        last_name = n[-1]
-    else:
-        first_name = ''
-        last_name = n[0]
-
-
-    # Create user
-    user = User.objects.create_user(username=username, email=email)
-    user.first_name = first_name
-    user.last_name = last_name
-    user.save()
-
-    return user
-
-def kiwipycon_createuser(request, data):
-    """Create user"""
-    email = data.get("email")
-    username = data.get("username")
-    password = data.get("password_1")
-    password = data.get("password_1")
-
-    # Create user
-    user = User.objects.create_user(
-        username=username, email=email, password=password)
-    user.first_name = data.get("first_name")
-    user.last_name = data.get("last_name")
-    user.save()
-
-    # Log in user
-    from django.contrib.auth import authenticate
-    user = authenticate(username=username, password=password)
-
-    from django.contrib.auth import login
-    login(request, user)
-
-    profile = user.get_profile()
-    photo = request.FILES.get('photo', None)
-    filename= None
-    if photo:
-        filename = handle_uploaded_photo(user, request.FILES['photo'])
-    if filename:
-        profile.photo = filename
-    #print photo, filename
-
-    profile.url = data.get("url")
-    profile.about = data.get("about")
-    profile.save()
-
-    return user
-
-def handle_uploaded_photo(user, ufile):
-    usermedia = settings.USER_MEDIA_ROOT
-    filename = ufile.name
-    ext = filename.split('.')[-1]
-    filesize = ufile.size
-    filecontent = ufile.read()
-    userfilename = 'user-%d.%s' % (user.id, ext)
-    if not filecontent:
-        return None
-
-    #save
-    foutname = os.path.join(usermedia, userfilename)
-
-    fout = file(foutname, 'wb')
-    fout.write(filecontent)
-    fout.close()
-
-    # crop and resize
-    image = Image.open(foutname)
-    pw = image.size[0]
-    ph = image.size[1]
-    nw = nh = 80
-    if (pw, ph) != (nw, nh):
-        pr = float(pw) / float(ph)
-        nr = float(nw) / float(nh)
-
-        if pr > nr:
-            # photo aspect is wider than destination ratio
-            tw = int(round(nh * pr))
-            image = image.resize((tw, nh), Image.ANTIALIAS)
-            l = int(round(( tw - nw ) / 2.0))
-            image = image.crop((l, 0, l + nw, nh))
-        elif pr < nr:
-            # photo aspect is taller than destination ratio
-            th = int(round(nw / pr))
-            image = image.resize((nw, th), Image.ANTIALIAS)
-            t = int(round(( th - nh ) / 2.0))
-            #print((0, t, nw, t + nh))
-            image = image.crop((0, t, nw, t + nh))
-        else:
-            # photo aspect matches the destination ratio
-            image = image.resize((nw, nh), Image.ANTIALIAS)
-
-        image.save(str(foutname))
-    return userfilename
-
--- a/project/kiwipycon/user/views.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-#python
-from urlparse import urlparse
-import json
-import urllib
-import os
-
-#django
-from django.conf import settings
-from django.db.models import Q
-from django.http import HttpResponse
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.core.urlresolvers import reverse
-from django.db.models.signals import post_save
-
-#django.contrib
-from django.contrib.auth.decorators import login_required
-from django.contrib.auth.forms import AuthenticationForm
-from django.contrib.auth.forms import PasswordChangeForm
-from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
-
-#PIL
-from PIL import Image
-
-#kiwipycon
-from project.kiwipycon.utils import set_message_cookie
-from project.kiwipycon.talk.models import Talk
-from project.kiwipycon.registration.models import Registration
-from project.kiwipycon.registration.models import Wifi
-from project.kiwipycon.registration.forms import WifiForm
-from project.kiwipycon.sponsor.models import Sponsor
-
-from .utils import kiwipycon_createuser
-from .utils import handle_uploaded_photo
-from .forms import RegisterForm
-from .forms import EditProfileForm
-from .forms import UsernameForm
-
-@login_required
-def account(request, template_name="user/account.html"):
-    """Displays the main screen of the current user's account.
-    """
-    user = request.user
-    profile = user.get_profile()
-
-    talks = Talk.objects.filter(speaker=user)
-    try:
-        registration = Registration.objects.get(registrant=user)
-    except ObjectDoesNotExist:
-        registration = None
-    try:
-        wifiobj = Wifi.objects.get(user=user)
-    except ObjectDoesNotExist:
-        wifiobj = None
-
-    if profile.photo:
-        photo = os.path.join(settings.USER_MEDIA_URL, profile.photo)
-    else:
-        photo = '/img/user-default.png'
-
-    qstring = ""
-
-    wifi_comment = None
-    if wifiobj:
-        wifi_form = False
-    else:
-        if request.method == "POST":
-            wifi_form = WifiForm(request.POST)
-            if wifi_form.is_valid():
-                wifi_form.save(user)
-            wifi_comment = 'Thanks, your wifi preference has been saved'
-            wifi_form = None
-        else:
-            wifi_form = WifiForm()
-
-    return render_to_response(template_name, RequestContext(request, {
-        "form" : wifi_form, "comment": wifi_comment,
-        "user" : user, "profile" : profile, "photo" : photo,
-        "talks" : talks, "registration" : registration,
-    }))
-
-@login_required
-def edit_profile(request, template_name="user/editprofile.html"):
-    """Allows user to edit profile
-    """
-    user = request.user
-    profile = user.get_profile()
-
-    if request.method == "POST":
-        form = EditProfileForm(data=request.POST,
-                               files=request.FILES)
-
-        if form.is_valid():
-            photo = request.FILES.get('photo', None)
-            filename= None
-            if photo:
-                filename = handle_uploaded_photo(user, request.FILES['photo'])
-            if filename:
-                profile.photo = filename
-
-            user.email = form.data.get("email")
-            user.first_name = form.data.get("first_name")
-            user.last_name = form.data.get("last_name")
-            user.save()
-
-            profile.url = form.data.get("url")
-            profile.about = form.data.get("about")
-            profile.save()
-
-            redirect_to = reverse("kiwipycon_account")
-            return set_message_cookie(redirect_to,
-                    msg = u"Your profile has been changed.")
-
-    else:
-        form = EditProfileForm(initial={"email" : user.email,
-                                        "email2" : user.email, # hidden field
-                                        "first_name" : user.first_name,
-                                        "last_name" : user.last_name,
-                                        "url" : profile.url,
-                                        "about" : profile.about,
-                                        })
-
-    return render_to_response(template_name, RequestContext(request, {
-        "form": form
-    }))
-
-def login(request, template_name="user/login.html"):
-    """Custom view to login or register/login a user.
-    Integration of register and login form
-    It uses Django's standard AuthenticationForm, though.
-    """
-    user = request.user
-    if user.is_authenticated():
-        redirect_to = reverse("kiwipycon_account")
-        return set_message_cookie(redirect_to,
-                msg = u"Redirected to account from login form.")
-
-    # Using Djangos default AuthenticationForm
-    login_form = AuthenticationForm()
-    register_form = RegisterForm()
-
-    if request.POST.get("action") == "login":
-        login_form = AuthenticationForm(data=request.POST)
-
-        if login_form.is_valid():
-            redirect_to = request.POST.get("next")
-            # Light security check -- make sure redirect_to isn't garbage.
-            if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
-                redirect_to = reverse("kiwipycon_account")
-
-            from django.contrib.auth import login
-            login(request, login_form.get_user())
-
-            return set_message_cookie(redirect_to, msg = u"You have been logged in.")
-
-    elif request.POST.get("action") == "register":
-        register_form = RegisterForm(data=request.POST)
-        if register_form.is_valid():
-
-            user = kiwipycon_createuser(request, register_form.data)
-
-            redirect_to = request.POST.get("next")
-            if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
-                redirect_to = reverse("kiwipycon_account")
-
-            return set_message_cookie(
-                redirect_to, msg = u"You have been registered and logged in.")
-
-    # Get next_url
-    next_url = request.REQUEST.get("next")
-    if next_url is None:
-        next_url = request.META.get("HTTP_REFERER")
-    if next_url is None:
-        next_url = reverse("kiwipycon_account")
-    # Get just the path of the url. See django.contrib.auth.views.login for more
-    next_url = urlparse(next_url)
-    next_url = next_url[2]
-
-    try:
-        login_form_errors = login_form.errors["__all__"]
-    except KeyError:
-        login_form_errors = None
-
-    return render_to_response(template_name, RequestContext(request, {
-        "login_form" : login_form,
-        "login_form_errors" : login_form_errors,
-        "register_form" : register_form,
-        "next_url" : next_url,
-    }))
-
-def logout(request):
-    """Custom method to logout a user.
-
-    The reason to use a custom logout method is just to provide a login and a
-    logoutmethod on one place.
-    """
-    from django.contrib.auth import logout
-    logout(request)
-
-    redirect_to = '/'
-    return set_message_cookie(redirect_to, msg = u"You have been logged out.")
-
-@login_required
-def password(request, template_name="user/password.html"):
-    """Changes the password of current user.
-    """
-    if request.method == "POST":
-        form = PasswordChangeForm(request.user, request.POST)
-        if form.is_valid():
-            form.save()
-            redirect_to = reverse("kiwipycon_account")
-            return set_message_cookie(redirect_to,
-                    msg = u"Your password has been changed.")
-    else:
-        form = PasswordChangeForm(request.user)
-
-    return render_to_response(template_name, RequestContext(request, {
-        "form" : form
-    }))
-
-@login_required
-def username(request, template_name="user/username.html"):
-    """Saves the username from the data form.
-    """
-    if request.method == "POST":
-        username_form = UsernameForm(initial={"username" : request.user.username}, data=request.POST)
-        if username_form.is_valid():
-            request.user.username = username_form.cleaned_data.get("username")
-            request.user.save()
-            redirect_to = reverse("kiwipycon_account")
-            return set_message_cookie(redirect_to,
-                    msg = u"Your username has been changed.")
-    else:        
-        username_form = UsernameForm(initial={"username" : request.user.username})
-
-    return render_to_response(template_name, RequestContext(request, {
-        "form": username_form
-    }))
-
-
-def get_usernames(request):
-    """Returns in json the list of ten possible usernames
-    starting with the last pattern in the comma separated string
-    """
-
-    get_params = request.GET
-    authors_str = get_params.get('input')
-
-    if not authors_str:
-        return HttpResponse(json.dumps(''))
-
-    authors = authors_str.split(',')
-    search_author = authors[-1].strip()
-
-    users = User.objects.filter(
-        Q(username__istartswith=search_author) | Q(
-        first_name__istartswith=search_author) | Q(
-        last_name__istartswith=search_author))
-
-    results = [{'id': '',
-                'info': 'plugin_header',
-                'value': 'User Names'
-              }]
-    
-    for user in users:
-        results.append(
-            {'id': 'author_name',
-             'info': str(user.get_full_name()),
-             'value': str(user.username)
-            })
-
-    json_response = {'results': results}
-
-    return HttpResponse(json.dumps(json_response))
\ No newline at end of file
--- a/project/kiwipycon/utils.py	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-#python
-import urllib
-import datetime
-import re
-from random import randint
-
-#django
-from django.http import HttpResponseRedirect
-
-def kiwipycon_quote(string, encoding="utf-8"):
-    """Encodes string to encoding before quoting.
-    """
-    return urllib.quote(string.encode(encoding))
-
-# from LFS
-def set_message_cookie(url, msg):
-    """Creates response object with given url and adds message cookie with passed
-    message.
-    """
-
-    # We just keep the message two seconds.
-    max_age = 2
-    expires = datetime.datetime.strftime(
-        datetime.datetime.utcnow() +
-        datetime.timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT")
-
-    response = HttpResponseRedirect(url)
-    response.set_cookie("message", kiwipycon_quote(msg), max_age=max_age, expires=expires)
-
-    return response
-
-# from django-snippets
-def slugify(inStr):
-    removelist = ["a", "an", "as", "at", "before", "but", "by", "for","from","is", "in", "into", "like", "of", "off", "on", "onto","per","since", "than", "the", "this", "that", "to", "up", "via","with"];
-    for a in removelist:
-        aslug = re.sub(r'\b'+a+r'\b','',inStr)
-    aslug = re.sub('[^\w\s-]', '', aslug).strip().lower()
-    aslug = re.sub('\s+', '-', aslug)
-    return len(aslug) > 50 and '%s-%d' % (aslug[:43], randint(100000,999999)) or aslug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/context_processors.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,17 @@
+from datetime import datetime
+
+from django.conf import settings
+
+from project.kiwipycon.sponsor.models import Sponsor
+
+def sponsors(request):
+    sponsors = Sponsor.objects.all()
+    gold_sponsors = sponsors.filter(type='gold')
+    silver_sponsors = sponsors.filter(type='silver')
+    schwag_sponsors = sponsors.filter(type='schwag')
+    return {
+            'sponsors': {'gold': gold_sponsors,
+                         'silver': silver_sponsors,
+                         'schwag': schwag_sponsors}
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/admin.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from django.contrib import admin
+
+from project.kiwipycon.proceedings.models import Paper
+
+
+class PaperAdmin(admin.ModelAdmin):
+    list_display = ('title', 'abstract')
+    list_filter = ('title', 'authors')
+    search_fields = ('title', 'abstract', 'authors')
+    fieldsets = (
+        ('Details', {
+            'fields': ('title', 'abstract', 'body', 'authors')
+        }),
+    )
+
+admin.site.register(Paper, PaperAdmin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/booklet/mk_booklet.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,94 @@
+# encoding: utf-8
+
+import os
+import sys
+import codecs
+import re
+
+try:
+    from sanum import model
+except:
+    root_dir = os.path.abspath(os.getcwd() + '/../../')
+    os.chdir(root_dir)
+    sys.path.append(root_dir)
+    from sanum import model
+
+import sanum
+
+import turbogears
+turbogears.update_config(configfile="dev.cfg",
+                         modulename="sanum.config")
+
+
+from mk_scipy_paper import tex2pdf, current_dir , copy_files, preamble, \
+        render_abstract, addfile, sourcedir, outdir, outfilename
+
+
+def hack_include_graphics(latex_text, attach_dir):
+    """ Replaces all the \includegraphics call with call that impose the
+        width to be 0.9\linewidth.
+    """
+    latex_text = re.sub(r'\\includegraphics(\[.*\])?\{',
+                        r'\includegraphics\1{' + attach_dir,
+                        latex_text)
+    return latex_text
+
+
+class MyStringIO(object):
+    """ An unicode-friendly stringIO-like object.
+    """
+
+    def __init__(self):
+        self.lines = []
+
+    def write(self, line):
+        self.lines.append(line)
+
+    def getvalue(self):
+        return u''.join(self.lines)
+
+def mk_booklet_tex(outfilename):
+    """ Generate the entire booklet latex file.
+    """
+    outfile = codecs.open(outfilename, 'w', 'utf-8')
+    preamble(outfile)
+    copy_files()
+    #addfile(outfile, sourcedir + os.sep + 'title.tex')
+    addfile(outfile, sourcedir + os.sep + 'introduction.tex')
+
+    #outfile.write(ur'\setcounter{page}{0}' + '\n')
+
+    #from sanum.controllers import Root as Controller
+    abstracts = model.Abstract.select()
+    for abstract in abstracts:
+        if not abstract.approved:
+            continue
+        print abstract.title
+        # Hack: I don't use a stringIO, because it is not unicode-safe.
+        tmpout = MyStringIO()
+        # Hack: I don't wont to be bound to the controller, to be
+        # abstractle to run without cherrypy.
+        #attach_dir = Controller._paper_attach_dir(abstract.id)
+        attach_dir = os.path.abspath(os.sep.join(
+                    (os.path.dirname(sanum.__file__), 'static', 
+                    'papers', '%i' % abstract.id))) + os.sep
+        render_abstract(tmpout, abstract)
+        outstring = hack_include_graphics(tmpout.getvalue(),
+                            attach_dir)
+        outfile.write(outstring)
+        #outfile.write(ur'\fillbreak' + '\n')
+
+    outfile.write(ur'\end{document}' + '\n')
+
+
+
+
+def mk_booklet(outfilename=outfilename):
+    """ Generate the entire booklet pdf file.
+    """
+    name, ext = os.path.splitext(outfilename)
+    mk_booklet_tex(name + '.tex')
+    return tex2pdf(name, remove_tex=False, timeout=60)
+
+if __name__ == '__main__':
+    mk_booklet(outfilename)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/booklet/mk_scipy_paper.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,463 @@
+# encoding: utf-8
+
+import os
+import re
+import sys
+import shutil
+import codecs
+from glob import glob
+
+from docutils import core as docCore
+
+conf_name = 'SciPy2009'
+
+current_dir = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet'
+
+outdir = current_dir + os.sep + 'output'
+
+sourcedir = current_dir + os.sep + 'sources'
+try:
+    os.mkdir(outdir)
+except:
+    pass
+
+outfilename = outdir + os.sep + 'booklet.tex'
+
+##############################################################################
+# Routines for supervised execution
+##############################################################################
+
+from threading import Thread
+import os
+import signal
+from subprocess import Popen
+from time import sleep
+
+def delayed_kill(pid, delay=10):
+    sleep(delay)
+    try:
+        os.kill(pid, signal.SIGTERM)
+    except OSError:
+        pass
+
+def supervise_popen(command, timeout=10):
+    process = Popen(command)
+    Thread(target=delayed_kill, args=(process.pid,timeout),).start()
+
+    process.wait()
+
+
+
+##############################################################################
+# LaTeX generation functions.
+##############################################################################
+
+def protect(string):
+    r''' Protects all the "\" in a string by adding a second one before
+
+    >>> protect(r'\foo \*')
+    '\\\\foo \\\\*'
+    '''
+    return re.sub(r"\\", r"\\\\", string)
+
+
+def safe_unlink(filename):
+    """ Remove a file from the disk only if it exists, if not r=fails silently
+    """
+    if os.path.exists(filename):
+        os.unlink(filename)
+
+rxcountpages = re.compile(r"$\s*/Type\s*/Page[/\s]", re.MULTILINE|re.DOTALL)
+
+def count_pages(filename):
+    data = file(filename,"rb").read()
+    return len(rxcountpages.findall(data))
+
+
+def tex2pdf(filename, remove_tex=True, timeout=10, runs=2):
+    """ Compiles a TeX file with pdfLaTeX (or LaTeX, if or dvi ps requested)
+        and cleans up the mess afterwards
+    """
+    current_dir = os.getcwd()
+    os.chdir(os.path.dirname(filename))
+    print >> sys.stderr, "Compiling document to pdf"
+    basename = os.path.splitext(os.path.basename(filename))[0]
+    if os.path.exists(basename + '.pdf'):
+        os.unlink(basename + '.pdf')
+    for _ in range(runs):
+        supervise_popen(("pdflatex",  "--interaction", "scrollmode",
+                        os.path.basename(filename)), timeout=timeout)
+    error_file = None
+    errors =  file(os.path.abspath(basename + '.log')).readlines()[-1]
+    if not os.path.exists(basename + '.pdf') or \
+                                    "Fatal error" in errors:
+        error_file = os.path.abspath(basename + '.log')
+    if remove_tex:
+        safe_unlink(filename+".tex")
+        safe_unlink(filename+".log")
+    safe_unlink(filename+".aux")
+    safe_unlink(filename+".out")
+    os.chdir(current_dir)
+    return error_file
+
+
+def rst2latex(rst_string, no_preamble=True, allow_latex=True):
+    """ Calls docutils' engine to convert a rst string to a LaTeX file.
+    """
+    overrides = {'output_encoding': 'utf-8', 'initial_header_level': 3,
+                 'no_doc_title': True, 'use_latex_citations': True, 
+                 'use_latex_footnotes':True}
+    if allow_latex:
+        rst_string = u'''.. role:: math(raw)
+                    :format: latex
+                    \n\n''' + rst_string
+    tex_string = docCore.publish_string(
+                source=rst_string,
+                writer_name='latex2e', 
+                settings_overrides=overrides)
+    if no_preamble:
+        extract_document = \
+            re.compile(r'.*\\begin\{document\}(.*)\\end\{document\}',
+            re.DOTALL)
+        matches = extract_document.match(tex_string)
+        tex_string = matches.groups()[0]
+    return tex_string
+
+
+def get_latex_preamble():
+    """ Retrieve the required preamble from docutils.
+    """
+    full_document = rst2latex('\n', no_preamble=False)
+    preamble = re.split(r'\\begin\{document\}', full_document)[0]
+    ## Remove the documentclass.
+    preamble = r"""
+                %s
+                \makeatletter
+                \newcommand{\class@name}{gael}
+                \makeatother
+                \usepackage{ltxgrid}
+                %s
+                """ % (
+                    preamble.split('\n')[0],
+                    '\n'.join(preamble.split('\n')[1:]),
+                )
+    return preamble
+
+
+##############################################################################
+# Functions to generate part of the booklet
+##############################################################################
+def addfile(outfile, texfilename):
+    """ Includes the content of a tex file in our outfile.
+    """
+    include = codecs.open(texfilename, 'r')
+    data = include.readlines()
+    outfile.write(ur'\thispagestyle{empty}' + u'\n')
+    outfile.writelines(data)
+
+
+def preamble(outfile):
+    outfile.write(r'''
+    %s
+    \usepackage{abstracts}
+    \usepackage{ltxgrid}
+    \usepackage{amssymb,latexsym,amsmath,amsthm}
+    \usepackage{longtable}
+    \geometry{left=.8cm, textwidth=17cm, bindingoffset=0.6cm,
+                textheight=25.3cm, twoside}
+    \usepackage{hyperref}
+    \hypersetup{pdftitle={Proceedings of the 8th Annual Python in Science Conference}}
+    \begin{document}
+
+    '''.encode('utf-8') % get_latex_preamble())
+
+    # XXX SciPy08 should not be hard coded, but to run out of the webapp
+
+def hack_include_graphics(latex_text):
+    """ Replaces all the \includegraphics call with call that impose the
+        width to be 0.9\linewidth.
+    """
+    latex_text = re.sub(r'\\setlength\{\\rightmargin\}\{\\leftmargin\}',
+                        r'\\setlength{\\leftmargin}{4ex}\\setlength{\\rightmargin}{0ex}',
+                        latex_text)
+    latex_text = re.sub(r'\\begin\{quote\}\n\\begin\{itemize\}',
+                        r'\\begin{itemize}',
+                        latex_text)
+    latex_text = re.sub(r'\\end\{itemize\}\n\\end\{quote\}',
+                        r'\\end{itemize}',
+                        latex_text)
+    latex_text = re.sub(r'\\includegraphics(\[.*\])?\{',
+                        r'\includegraphics[width=\linewidth]{',
+                        latex_text)
+    latex_text = re.sub(r'\\href\{([^}]+)\}\{http://(([^{}]|(\{[^}]*\}))+)\}', 
+                        r'''%
+% Break penalties to have URL break easily:
+\mathchardef\UrlBreakPenalty=0
+\mathchardef\UrlBigBreakPenalty=0
+%\hskip 0pt plus 2em
+\href{\1}{\url{\1}}''',
+                        latex_text)
+    latex_text = re.sub(r'\\href\{([^}]+)\}\{https://(([^{}]|(\{[^}]*\}))+)\}', 
+                        r'''%
+% Break penalties to have URL break easily:
+\mathchardef\UrlBreakPenalty=0
+\mathchardef\UrlBigBreakPenalty=0
+\linebreak
+\href{\1}{\url{\1}}''',
+                        latex_text)
+
+    return latex_text
+
+
+def render_abstract(outfile, abstract, start_page=None):
+    """ Writes the LaTeX string corresponding to one abstract.
+    """
+    if start_page is not None:
+        outfile.write(r"""
+\setcounter{page}{%i}
+""" % start_page)
+    else:
+        if hasattr(abstract, 'start_page'):
+            start_page = abstract.start_page
+        else:
+            start_page = 1
+    if not abstract.authors:
+        author_list = abstract.owners
+    else:
+        author_list = abstract.authors
+    authors = []
+    print dir(author_list[0])
+    for author in author_list:
+        # If the author has no surname, he is not an author 
+        if author.surname:
+            if author.email_address:
+                email = r'(\email{%s})' % author.email_address
+            else:
+                email = ''
+            authors.append(ur'''\otherauthors{
+                            %s %s
+                            %s --
+                            \address{%s, %s}
+                            }''' % (author.first_names, author.surname,
+                                    email,
+                                    author.institution,
+                                    author.city))
+    if authors:
+        authors = u'\n'.join(authors)
+        authors += r'\addauthorstoc{%s}' % ', '.join(
+                '%s. %s' % (author.first_names[0], author.surname)
+                for author in author_list
+                )
+        author_cite_list = ['%s. %s' % (a.first_names[0], a.surname) 
+                                for a in author_list]
+        if len(author_cite_list) > 4:
+            author_cite_list = author_cite_list[:3]
+            author_cite_list.append('et al.')
+        citation = ', '.join(author_cite_list) + \
+        'in Proc. SciPy 2009, G. Varoquaux, S. van der Walt, J. Millman (Eds), '
+        copyright = '\\copyright 2009, %s' % ( ', '.join(author_cite_list))
+    else:
+        authors = ''
+        citation = 'Citation'
+        copyright = 'Copyright'
+    if hasattr(abstract, 'num_pages'):
+        citation += 'pp. %i--%i' % (start_page, start_page +
+                                        abstract.num_pages)
+    else:
+        citation += 'p. %i'% start_page
+    if hasattr(abstract, 'number'):
+        abstract.url = 'http://conference.scipy.org/proceedings/%s/paper_%i' \
+        % (conf_name, abstract.number)
+        url = r'\url{%s}' % abstract.url
+    else:
+        url = ''
+    paper_text = abstract.paper_text
+    if paper_text == '':
+        paper_text = abstract.summary
+    # XXX: It doesn't seem to be right to be doing this, but I get a
+    # nasty UnicodeDecodeError on some rare abstracts, elsewhere.
+    paper_text = codecs.utf_8_decode(hack_include_graphics(
+                                rst2latex(paper_text)))[0]
+    paper_abstract = abstract.paper_abstract
+    if paper_abstract is None:
+        paper_abstract = ''
+    if not paper_abstract=='':
+        paper_abstract = ur'\begin{abstract}%s\end{abstract}' % \
+                    paper_abstract#.encode('utf-8')
+    abstract_dict = {
+            'text': paper_text.encode('utf-8'),
+            'abstract': paper_abstract.encode('utf-8'),
+            'authors': authors.encode('utf-8'),
+            'title': abstract.title.encode('utf-8'),
+            'citation': citation.encode('utf-8'),
+            'copyright': copyright.encode('utf-8'),
+            'url': url.encode('utf-8'),
+        }
+    outfile.write(codecs.utf_8_decode(ur'''
+\phantomsection
+\hypertarget{chapter}{} 
+\vspace*{-2em}
+
+\resetheadings{%(title)s}{%(citation)s}{%(url)s}{%(copyright)s}
+\title{%(title)s}
+
+\begin{minipage}{\linewidth}
+%(authors)s
+\end{minipage}
+
+\noindent\rule{\linewidth}{0.2ex}
+\vspace*{-0.5ex}
+\twocolumngrid
+%(abstract)s
+
+\sloppy
+
+%(text)s
+
+\fussy
+\onecolumngrid
+\smallskip
+\vfill
+\filbreak
+\clearpage
+
+'''.encode('utf-8') % abstract_dict )[0])
+
+def copy_files(dest=outfilename):
+    """ Copy the required file from the source dir to the output dir.
+    """
+    dirname = os.path.dirname(dest)
+    if dirname == '':
+        dirname = '.'
+    for filename in glob(sourcedir+os.sep+'*'):
+        destfile = os.path.abspath(dirname + os.sep +
+                                os.path.basename(filename))
+        shutil.copy2(filename, destfile)
+
+
+def mk_abstract_preview(abstract, outfilename, attach_dir, start_page=None):
+    """ Generate a preview for an given paper.
+    """
+    copy_files()
+    outdir = os.path.dirname(os.path.abspath(outfilename))
+    for f in glob(os.path.join(attach_dir, '*')):
+        if  os.path.isdir(f) and not os.path.exists(f):
+            os.makedirs(f)
+        else:
+            if not outdir == os.path.dirname(os.path.abspath(f)):
+                shutil.copy2(f, outdir)
+    for f in glob(os.path.join(sourcedir, '*')):
+        if  os.path.isdir(f):
+            os.makedirs(f)
+        else:
+            destfile = os.path.abspath(os.path.join(outdir, f))
+            shutil.copy2(f, outdir)
+
+    outbasename = os.path.splitext(outfilename)[0]
+    outfilename = outbasename + '.tex'
+
+    outfile = codecs.open(outfilename, 'w', 'utf-8')
+    preamble(outfile)
+    render_abstract(outfile, abstract, start_page=start_page)
+    outfile.write(ur'\end{document}' + u'\n')
+    outfile.close()
+
+    tex2pdf(outbasename, remove_tex=False)
+    abstract.num_pages = count_pages(outbasename + '.pdf')
+
+    # Generate the tex file again, now that we know the length.
+    outfile = codecs.open(outfilename, 'w', 'utf-8')
+    preamble(outfile)
+    render_abstract(outfile, abstract, start_page=start_page)
+    outfile.write(ur'\end{document}' + u'\n')
+    outfile.close()
+
+    return tex2pdf(os.path.splitext(outfilename)[0], remove_tex=False)
+
+
+##############################################################################
+# Code for using outside of the webapp.
+##############################################################################
+
+def mk_zipfile():
+    """ Generates a zipfile with the required files to build an
+        abstract.
+    """
+    from zipfile import ZipFile
+    zipfilename = os.path.join(os.path.dirname(__file__), 
+                            'mk_scipy_paper.zip')
+    z = ZipFile(zipfilename, 'w')
+    for filename in glob(os.path.join(sourcedir, '*')):
+        if not os.path.isdir(filename):
+            z.write(filename, arcname='source/' + os.path.basename(filename))
+    z.write(__file__, arcname='mk_scipy_paper.py')
+    return zipfilename
+
+class Bunch(dict):
+    def __init__(self, **kwargs):
+        dict.__init__(self, **kwargs)
+        self.__dict__ = self
+
+    def __reprt(self):
+        return repr(self.__dict__)
+
+author_like = Bunch(
+        first_names='XX', 
+        surname='XXX',
+        email_address='xxx@XXX',
+        institution='XXX',
+        address='XXX',
+        country='XXX'
+)
+
+
+abstract_like = Bunch(
+        paper_abstract='An abstract',
+        authors=[author_like, ],
+        title='',
+    )
+
+if __name__ == '__main__':
+    from optparse import OptionParser
+    parser = OptionParser()
+    parser.add_option("-o", "--output", dest="outfilename",
+                    default="./paper.pdf",
+                    help="output to FILE", metavar="FILE")
+    parser.usage = """%prog [options] rst_file [data_file]
+    Compiles a given rest file and information file to pdf for the SciPy
+    proceedings.
+    """
+    
+    (options, args) = parser.parse_args()
+    if not len(args) in (1, 2):
+        print "One or two arguments required: the input rest file and " \
+                "the input data file"
+        print ''
+        parser.print_help()
+        sys.exit(1)
+    infile = args[0]
+    if len(args)==1:
+        data_file = 'data.py'
+        if os.path.exists('data.py'):
+            print "Using data file 'data.py'"
+        else:
+            print "Generating the data file and storing it in data.py"
+            print "You will need to edit this file to add title, author " \
+                "information, and abstract."
+            abstract = abstract_like
+            file('data.py', 'w').write(repr(abstract))
+    elif len(args)==2:
+        data_file = args[1]
+    
+    abstract = Bunch( **eval(file(data_file).read()))
+    abstract.authors = [Bunch(**a) for a in abstract.authors]
+
+    abstract['summary'] = u''
+    abstract['paper_text'] = file(infile).read().decode('utf-8')
+
+    outfilename = options.outfilename
+
+    mk_abstract_preview(abstract, options.outfilename, 
+                        os.path.dirname(options.outfilename))
+    # Ugly, but I don't want to wait on the thread.
+    sys.exit()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/forms.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from django import forms
+
+
+class ProceedingsForm(forms.Form):
+    """Form for proceedings.
+    """
+
+    title = forms.CharField(required=True, label=u'Title',
+                            widget=forms.TextInput(attrs={'size':'70'}))
+
+    abstract = forms.CharField(
+        widget=forms.Textarea(attrs={'cols': '80', 'rows': '8'}),
+        required=True, label=u'Abstract',
+        help_text=u'Upto 200 words. Content must strictly be in reSt format.')
+
+    body = forms.CharField(
+        widget=forms.Textarea(attrs={'cols': '80', 'rows': '25'}),
+        required=False, label=u'Body', help_text=u'Approximately 7 pages. '
+        'Content must strictly be in reSt format.')
+
+    rst_file = forms.FileField(
+        required=False, label=u'reStructuredText file',
+        help_text=u'The file should contain two sections, one with a heading '
+        "'Abstract' and other with a heading 'Body'.")
+
+    authors = forms.CharField(
+        required=False, label=u'Author(s)',
+        help_text=u'Comma separated list of User ID of the author(s).')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/migrations/0001_initial.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+
+from south.db import db
+from django.db import models
+from project.kiwipycon.proceedings.models import *
+
+class Migration:
+    
+    def forwards(self, orm):
+        
+        # Adding model 'Paper'
+        db.create_table('proceedings_paper', (
+            ('body', models.TextField()),
+            ('abstract', models.TextField()),
+            ('id', models.AutoField(primary_key=True)),
+            ('title', models.CharField(max_length=200)),
+        ))
+        db.send_create_signal('proceedings', ['Paper'])
+        
+        # Adding model 'Attachments'
+        db.create_table('proceedings_attachments', (
+            ('paper', models.ForeignKey(orm.Paper)),
+            ('id', models.AutoField(primary_key=True)),
+            ('attachments', models.FileField(upload_to='attachments/%Y/%m/%d')),
+        ))
+        db.send_create_signal('proceedings', ['Attachments'])
+        
+        # Adding ManyToManyField 'Paper.authors'
+        db.create_table('proceedings_paper_authors', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('paper', models.ForeignKey(Paper, null=False)),
+            ('user', models.ForeignKey(User, null=False))
+        ))
+        
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'Paper'
+        db.delete_table('proceedings_paper')
+        
+        # Deleting model 'Attachments'
+        db.delete_table('proceedings_attachments')
+        
+        # Dropping ManyToManyField 'Paper.authors'
+        db.delete_table('proceedings_paper_authors')
+        
+    
+    
+    models = {
+        'proceedings.paper': {
+            'abstract': ('models.TextField', [], {}),
+            'authors': ('models.ManyToManyField', ['User'], {}),
+            'body': ('models.TextField', [], {}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'title': ('models.CharField', [], {'max_length': '200'})
+        },
+        'auth.user': {
+            '_stub': True,
+            'id': ('models.AutoField', [], {'primary_key': 'True'})
+        },
+        'proceedings.attachments': {
+            'attachments': ('models.FileField', [], {'upload_to': "'attachments/%Y/%m/%d'"}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'paper': ('models.ForeignKey', ['Paper'], {})
+        }
+    }
+    
+    complete_apps = ['proceedings']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/models.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from django.db import models
+from django.contrib.auth.models import User
+
+
+class Paper(models.Model):
+    """Data model for storing proceedings paper.
+    """
+
+    # Title of the paper
+    title = models.CharField(max_length=200)
+
+    # Abstract to be published with the paper
+    abstract = models.TextField()
+
+    # Body text of the paper
+    body = models.TextField()
+
+    # Authors
+    authors = models.ManyToManyField(User)
+
+
+class Attachments(models.Model):
+    """Stores attachments for papers.
+    """
+
+    # Attachment for generating paper
+    attachments = models.FileField(upload_to='attachments/%Y/%m/%d')
+
+    # The paper to which this attachment belongs to
+    paper = models.ForeignKey(Paper)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/proceedings/views.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,203 @@
+  # -*- coding: utf-8 -*-
+
+import os
+
+from django.contrib.auth import login
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.forms import AuthenticationForm
+from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+
+from project.kiwipycon.proceedings.models import Paper
+from project.kiwipycon.user.forms import RegisterForm
+from project.kiwipycon.user.models import UserProfile
+from project.kiwipycon.utils import set_message_cookie
+from project.kiwipycon.proceedings.booklet import mk_scipy_paper
+from project.kiwipycon.proceedings.forms import ProceedingsForm
+
+
+def handleUploadedFile(proceedings_form_data, rst_file):
+    """Handles the uploaded file content and process the form
+    """
+
+    title = proceedings_form_data.get('title')
+    abstract = proceedings_form_data.get('abstract')
+    body = proceedings_form_data.get('body')
+    authors = proceedings_form_data.get('authors')
+
+    if rst_file:
+        destination = open('some/file/name.txt', 'wb+')
+        for chunk in rst_file.chunks():
+            destination.write(chunk)
+        destination.close()
+
+    return title, abstract, body, authors
+
+
+@login_required
+def submit(request, id=None, template='proceedings/submit.html'):
+    """View to submit the proceedings paper.
+    """
+
+    user = request.user
+    if user.is_authenticated():
+        try:
+            profile = user.get_profile()
+        except:
+            profile, new = UserProfile.objects.get_or_create(user=user)
+            if new:
+                profile.save()
+    message = None
+
+    if request.method == 'POST':
+        register_form = RegisterForm(data=request.POST)
+
+        if request.POST.get('action', None) == 'login':
+            login_form = AuthenticationForm(data=request.POST)
+            if login_form.is_valid():
+
+                login(request, login_form.get_user())
+
+                redirect_to = reverse('kiwipycon_submit_proceedings')
+                return set_message_cookie(redirect_to,
+                        msg = u'You have been logged in.')
+
+        if request.POST.get('action', None) == 'register':
+            # add the new user
+            if register_form.is_valid():
+
+                user = kiwipycon_createuser(request, register_form.data)
+
+        proceedings_form = ProceedingsForm(data=request.POST,
+                                           files=request.FILES)
+  
+        if proceedings_form.is_valid():
+            if user.is_authenticated():
+                # Data from reSt file is appended to the data in fields
+                title, abstract, body, authors = handleUploadedFile(
+                    proceedings_form.cleaned_data, request.FILES.get('file'))
+
+                paper = edit(id, title=title,
+                    abstract=abstract, body=body,
+                    authors=authors) if id else create(title=title,
+                    abstract=abstract, body=body,
+                    authors=authors)
+
+                # Successfully saved. So get back to the edit page.
+                redirect_to = reverse('kiwipycon_submit_proceedings',
+                                  args=[paper.id])
+                return set_message_cookie(
+                redirect_to, msg = u'Thanks, your paper has been submitted.')
+            else:
+                # This is impossible. Something was wrong so return back
+                # to submit page
+                redirect_to = reverse('kiwipycon_submit_proceedings')
+                return set_message_cookie(
+                redirect_to, msg = u'Something is wrong here.')          
+    else:
+        if id:
+            # If id exists initialize the form with old values
+            paper = Paper.objects.get(id=id)
+            proceedings_form = ProceedingsForm(
+                initial={'title': paper.title,
+                         'abstract': paper.abstract,
+                         'body': paper.body,
+                         'authors': ', '.join([
+                             author.username for author in paper.authors.all()])
+                })
+        else:
+            # Otherwise create a new form
+            proceedings_form = ProceedingsForm()
+
+        register_form = RegisterForm()
+        login_form = AuthenticationForm()
+
+    context = RequestContext(request, {
+        'proceedings_form': proceedings_form,
+        'register_form' : register_form,
+        'message' : message,
+        'login_form' : login_form
+        })
+
+    context['id'] = id if id else None
+
+    return render_to_response(template, context)
+
+
+def create(**kwargs):
+    """View to create a new proceedings.
+    """
+
+    title = kwargs.get('title')
+    abstract = kwargs.get('abstract')
+    body = kwargs.get('body')
+    authors = kwargs.get('authors')
+
+    paper = Paper(title=title, abstract=abstract, body=body)
+    paper.save()
+
+    if authors:
+        authors = authors.split(',')
+        for author in authors:
+            user = User.objects.get(username=author.strip())
+            paper.authors.add(user)
+
+    return paper
+
+
+def edit(id, **kwargs):
+    """View to edit the proceedings paper.
+    """
+
+    paper = Paper.objects.get(id=id)
+
+    paper.title = kwargs.get('title')
+    paper.abstract = kwargs.get('abstract')
+    paper.body = kwargs.get('body')
+    authors = kwargs.get('authors')
+
+    if authors:
+        authors = authors.split(',')
+        for author in authors:
+            user = User.objects.get(username=author.strip())
+            paper.authors.add(user)
+
+    paper.save()
+
+    return paper
+
+
+def show_paper(request, id):
+    """Display the thumbnail of the rendered paper for download
+    """
+    
+    paper = Paper.objects.get(id=id)
+
+    paper_data = {
+      'paper_abstract': paper.abstract,
+      'authors': [
+          {'first_names': author.first_name,
+            'surname': author.last_name,
+            'address': 'XXX',
+            'country': 'XXX',
+            'email_address': 'XXX@xx.com',
+            'institution': 'XXX'
+           } for author in paper.authors.all()],
+      'title': paper.title
+      }
+    
+    abstract = mk_scipy_paper.Bunch(**paper_data)
+    abstract.authors = [mk_scipy_paper.Bunch(**a) for a in abstract.authors]
+
+    abstract['paper_text'] = paper.body
+
+    outfilename = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet/output/paper.pdf'
+    attach_dir = os.path.dirname('/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet/output/')
+    mk_scipy_paper.mk_abstract_preview(abstract, outfilename, attach_dir)
+
+    from django.http import HttpResponse
+    return HttpResponse('Machi')
+
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/admin.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django.contrib
+from django.contrib import admin
+
+#kiwipycon
+from .models import Registration
+from .models import Wifi
+
+class RegistrationAdmin(admin.ModelAdmin):
+    list_display = ('registrant', 'full_name', 'laptop', 'slug',
+            'email', 'city', 'organisation', 'occupation',
+            'postcode', 'tshirt', 'conference', 'tutorial',
+            'sprint', 'allow_contact')
+    fieldsets = (
+        ('Details', {
+            'fields': ('slug', 'registrant', 'organisation', 'occupation',
+                'city', 'tshirt')
+        }),
+        ('Information', {
+            'fields': ('allow_contact',),
+        }),
+    )
+
+    search_fields = ['registrant__username', 'registrant__email']
+
+    def email(self, obj):
+        return obj.registrant.email
+
+    def full_name(self, obj):
+        return obj.registrant.get_full_name()
+
+    def laptop(self, obj):
+        return obj.registrant.wifi_set.values()[0]['wifi']
+
+admin.site.register(Registration, RegistrationAdmin)
+
+class WifiAdmin(admin.ModelAdmin):
+    list_display = ('user', 'wifi',)
+    list_filter = ('wifi',)
+
+admin.site.register(Wifi, WifiAdmin)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/forms.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,179 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django import forms
+from django.core.exceptions import ObjectDoesNotExist
+
+#django.contrib
+from django.contrib.auth.models import User
+
+from .models import SIZE_CHOICES
+from .models import Registration
+from .models import Wifi
+from project.kiwipycon.sponsor.models import Sponsor
+
+class RegistrationSubmitForm(forms.Form):
+    """PyCon registration form
+    """
+    tshirt = forms.ChoiceField(choices=SIZE_CHOICES, required=True,
+        label=u'T-shirt size', help_text=u'Yes, we all get a t-shirt!')
+#    beverage = forms.CharField(required=True, label=u'Beverage',
+#        help_text=u'Your beverage of choice - coffee, tea etc',
+#        max_length=255,
+#        widget=forms.TextInput(attrs={'size':'50'}))
+#    diet = forms.CharField(required=False, label=u'Dietary',
+#        help_text=u'Special dietary requirements - vegetarian etc',
+#        max_length=255,
+#        widget=forms.TextInput(attrs={'size':'50'}))
+    organisation = forms.CharField(required=True, label=u'Organisation',
+        help_text=u'The primary organisation that you are a member of.',
+        max_length=255,
+        widget=forms.TextInput(attrs={'size':'50'}))
+    occupation = forms.CharField(required=True, label=u'Occupation',
+        help_text=u'Title of your occupation',
+        max_length=255,
+        widget=forms.TextInput(attrs={'size':'50'}))
+    city = forms.CharField(required=True, label=u'City',
+        help_text=u'City of residence',
+        max_length=255,
+        widget=forms.TextInput(attrs={'size':'50'}))
+    postcode = forms.CharField(required=False, label=u'Postcode',
+        help_text=u'This field is optional',
+        max_length=10,
+        widget=forms.TextInput(attrs={'size':'10'}))
+    allow_contact = forms.BooleanField(required=False, label=u'Contact',
+        help_text=u'May organizers of SciPy.in contact you after the event?')
+    conference = forms.BooleanField(required=False, label=u'Conference',
+        help_text=u"""Do you intend to attend the SciPy conference?  
+        Note: Only conference has an registration fee of Rs.200 which you will
+        pay on the spot.""")
+    tutorial = forms.BooleanField(required=False, label=u'Tutorial',
+        help_text=u'Do you intend to attend the tutorials?')
+    sprint = forms.BooleanField(required=False, label=u'Sprint',
+        help_text=u'Do you intend to attend the sprints?')
+#    party = forms.BooleanField(required=False, label=u'Pre-con party',
+#        help_text=u'Do you intend to attend the pre-conference party on Friday?')
+#    discount = forms.BooleanField(required=False, label=u'Student/Unwaged?',
+#        help_text=u'You will be required to present your Community Services '\
+#                'Card or Student ID on arrival.')
+#    sponsor = forms.CharField(required=False, label=u'Sponsor code',
+#        help_text=u'If attending as a sponsor please enter your sponsor code.',
+#        max_length=50,
+#        widget=forms.TextInput(attrs={'size':'20'}))
+
+    def demographic_fields(self):
+        return (self['organisation'],
+                self['occupation'],
+                self['city'],
+                self['postcode'])
+
+    def personal_fields(self):
+        return (self['tshirt'],
+                self['conference'],
+                self['tutorial'],
+                self['sprint'],
+                self['allow_contact'])
+
+#    def other_fields(self):
+#        return (self['sponsor'],)
+#
+#    def clean_sponsor(self):
+#        """Validates that the entered sponsor code is valid and within limits
+#        of allowed guests
+#        """
+#        sponsorcode = self.cleaned_data.get("sponsor")
+#        if sponsorcode:
+#            try:
+#                sponsor = Sponsor.objects.get(slug=sponsorcode)
+#            except ObjectDoesNotExist:
+#                raise forms.ValidationError(
+#                    u"The sponsor code you entered is not valid.")
+#            if sponsor:
+#                guests = sponsor.guests
+#                if guests == 0:
+#                    raise forms.ValidationError(
+#                        u"The sponsor code you entered is not valid.")
+#                count = Registration.objects.filter(
+#                            sponsor=sponsorcode).count()
+#                if count >= guests:
+#                    raise forms.ValidationError(
+#                    u"That sponsor has reached limit of guests.")
+#
+#
+#        return sponsorcode
+
+
+class RegistrationEditForm(RegistrationSubmitForm):
+    id = forms.CharField(widget=forms.HiddenInput)
+    sponsor = forms.CharField(required=False, widget=forms.HiddenInput)
+
+class WifiForm(forms.ModelForm):
+    """PyCon wifi form
+    """
+
+    def save(self, user):
+        wifi = Wifi(user=user, wifi=self.cleaned_data['wifi'])
+        wifi.save()
+        return wifi
+
+    class Meta:
+        model = Wifi
+        fields = ('wifi',)
+
+PC = (
+        ('all', 'all'),
+        ('paid', 'paid'),
+        ('not paid', 'not paid')
+        )
+HC = (
+        ('all', 'all'),
+        ('party', 'party'),
+        ('no party', 'no party')
+        )
+AC = (
+        ('all', 'all'),
+        ('0', '0'),
+        ('10', '10'),
+        ('20', '20'),
+        ('40', '40'),
+        )
+OC = (
+        ('email', 'email'),
+        ('amount', 'amount'),
+        )
+
+IC = (
+        ('Name', 'name'),
+        ('Email', 'email'),
+        ('Amount', 'amount'),
+        ('Organisation', 'organisation'),
+        ('Conference', 'conference'),
+        ('Tutorial', 'tutorial'),
+        ('Sprint', 'sprint'),
+        ('T-size', 'tshirt'),
+        )
+
+SC = (
+    ('all', 'all'),
+    ('S', 'S'),
+    ('M', 'M'),
+    ('L', 'L'),
+    ('XL', 'XL'),
+    )
+class RegistrationAdminSelectForm(forms.Form):
+    """
+    Used to make selection for csv download
+    """
+    by_payment = forms.ChoiceField(choices=PC, required=False,
+        label=u'By payment')
+    by_amount = forms.MultipleChoiceField(choices=AC, required=False,
+        label=u'By amount')
+    by_party = forms.ChoiceField(choices=HC, required=False,
+        label=u'by party')
+    by_tshirt = forms.ChoiceField(choices=SC, required=False,
+        label=u'by tshirt size')
+    order_by = forms.ChoiceField(choices=OC, required=False,
+        label=u'order results')
+    include = forms.MultipleChoiceField(choices=IC, required=False,
+        label=u'Include fields')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/labels.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,7 @@
+
+WIFI_CHOICES = (
+    ("0", "Yes"),
+    ('1', 'No'),
+    )
+
+WIFI_HELP = """Are you bringing a laptop to the event?"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/migrations/0001_initial.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+
+from south.db import db
+from django.db import models
+from project.kiwipycon.registration.models import *
+
+class Migration:
+    
+    def forwards(self, orm):
+        
+        # Adding model 'Registration'
+        db.create_table('registration_registration', (
+            ('slug', models.SlugField()),
+            ('registrant', models.ForeignKey(orm['auth.User'])),
+            ('organisation', models.CharField(max_length=255, blank=True)),
+            ('occupation', models.CharField(max_length=255, blank=True)),
+            ('city', models.CharField(max_length=255, blank=True)),
+            ('postcode', models.CharField(max_length=255, blank=True)),
+            ('tshirt', models.CharField(max_length=2)),
+            ('conference', models.BooleanField(default=False)),
+            ('tutorial', models.BooleanField(default=False)),
+            ('sprint', models.BooleanField(default=False)),
+            ('submitted', models.DateTimeField(auto_now_add=True)),
+            ('allow_contact', models.BooleanField(default=False)),
+            ('last_mod', models.DateTimeField(auto_now=True)),
+            ('id', models.AutoField(primary_key=True)),            
+        ))
+        db.send_create_signal('registration', ['Registration'])
+        
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'Registration'
+        db.delete_table('registration_registration')
+        
+    
+    
+    models = {
+        'auth.user': {
+            '_stub': True,
+            'id': ('models.AutoField', [], {'primary_key': 'True'})
+        },
+        'registration.registration': {
+            'allow_contact': ('models.BooleanField', [], {'default': 'False'}),
+            'city': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'last_mod': ('models.DateTimeField', [], {'auto_now': 'True'}),
+            'occupation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'organisation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'conference': ('models.BooleanField', [], {'default': 'False'}),
+            'tutorial': ('models.BooleanField', [], {'default': 'False'}),
+            'sprint': ('models.BooleanField', [], {'default': 'False'}),
+            'postcode': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'registrant': ('models.ForeignKey', ['User'], {}),
+            'slug': ('models.SlugField', [], {}),
+            'submitted': ('models.DateTimeField', [], {'auto_now_add': 'True'}),
+            'tshirt': ('models.CharField', [], {'max_length': '2'})
+        }
+    }
+    
+    complete_apps = ['registration']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/migrations/0002_create_wifi.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+from south.db import db
+from django.db import models
+from project.kiwipycon.registration.models import *
+
+class Migration:
+    
+    def forwards(self, orm):
+        
+        # Adding model 'Wifi'
+        db.create_table('registration_wifi', (
+            ('wifi', models.CharField(max_length=50)),
+            ('user', models.ForeignKey(orm['auth.User'])),
+            ('id', models.AutoField(primary_key=True)),
+        ))
+        db.send_create_signal('registration', ['Wifi'])
+        
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'Wifi'
+        db.delete_table('registration_wifi')
+        
+    
+    
+    models = {
+        'auth.user': {
+            '_stub': True,
+            'id': ('models.AutoField', [], {'primary_key': 'True'})
+        },
+        'registration.wifi': {
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'user': ('models.ForeignKey', ['User'], {}),
+            'wifi': ('models.CharField', [], {'max_length': '50'})
+        },
+        'registration.registration': {
+            'allow_contact': ('models.BooleanField', [], {'default': 'False'}),
+            'city': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'last_mod': ('models.DateTimeField', [], {'auto_now': 'True'}),
+            'occupation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'organisation': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'conference': ('models.BooleanField', [], {'default': 'False'}),
+            'tutorial': ('models.BooleanField', [], {'default': 'False'}),
+            'sprint': ('models.BooleanField', [], {'default': 'False'}),
+            'postcode': ('models.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'registrant': ('models.ForeignKey', ['User'], {}),
+            'slug': ('models.SlugField', [], {}),
+            'submitted': ('models.DateTimeField', [], {'auto_now_add': 'True'}),
+            'tshirt': ('models.CharField', [], {'max_length': '2'})
+        }
+    }
+    
+    complete_apps = ['registration']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/models.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django.db import models
+from django.contrib.auth.models import User
+
+from .utils import send_confirmation_payment_email
+from .utils import send_banking_fix_email
+
+from .labels import WIFI_CHOICES
+from .labels import WIFI_HELP
+
+SIZE_CHOICES = (
+    ('S', 'S'),
+    ('M', 'M'),
+    ('L', 'L'),
+    ('XL', 'XL'),
+    )
+
+class Wifi(models.Model):
+    """Defines wifi options at *PyCon"""
+    user = models.ForeignKey(User)
+    wifi = models.CharField(max_length=50, choices=WIFI_CHOICES,
+            help_text=WIFI_HELP, verbose_name="Laptop")
+
+class Registration(models.Model):
+    """Defines registration at *PyCon"""
+    slug = models.SlugField()
+    registrant = models.ForeignKey(User)
+    organisation = models.CharField(max_length=255, blank=True)
+    occupation = models.CharField(max_length=255, blank=True)
+    city = models.CharField(max_length=255, blank=True)
+    postcode = models.CharField(max_length=255, blank=True)
+#    beverage = models.CharField(max_length=255, blank=True)
+#    diet = models.CharField(max_length=255, blank=True)
+#    sponsor = models.CharField(max_length=255, blank=True)
+    tshirt = models.CharField(max_length=2, choices=SIZE_CHOICES)
+#    party = models.BooleanField(default=False)
+#    discount = models.BooleanField(default=False)
+
+    # scipy.in specific
+    conference = models.BooleanField(default=False)
+    # scipy.in specific
+    tutorial = models.BooleanField(default=False)
+    # scipy.in specific
+    sprint = models.BooleanField(default=False)
+
+#    amount = models.IntegerField(default=0)
+    allow_contact = models.BooleanField(default=False)
+#    payment = models.BooleanField(default=False)
+    submitted = models.DateTimeField(auto_now_add=True)
+    last_mod = models.DateTimeField(auto_now=True)
+
+    def __unicode__(self):
+        return 'Registration for user: <%s %s> %s' % (self.registrant.first_name,
+                self.registrant.last_name, self.registrant.email)
+
+#    def save(self, *args, **kwargs):
+#        if(self.id):
+#            old_reg = Registration.objects.get(pk=self.id)
+#            if(old_reg.payment == False and self.payment == True \
+#                    and not self.sponsor):
+#                send_confirmation_payment_email(self.registrant)
+#            if(old_reg.slug.startswith('NZ') and self.slug.startswith('KPC') \
+#                    and not self.sponsor):
+#                send_banking_fix_email(self.registrant, self.slug)
+#        super(Registration, self).save(args, kwargs)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/pdf.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,20 @@
+import os
+
+from django.conf import settings
+from django.template.loader import render_to_string
+
+def save_invoice(user, registration, template_name):
+    content = render_to_string(template_name,
+        {'registration' : registration, 'user': user})
+    filename = '%s.html' % registration.slug
+    filepath = os.path.join(settings.USER_MEDIA_PDF, filename)
+    save_to_file(content, filepath)
+
+def save_to_pdf(content, filepath):
+    import pisa
+    pisa.CreatePDF(str(content), file(filepath, 'wb'))
+
+def save_to_file(content, filepath):
+    fout = file(filepath, 'wb')
+    fout.write(content)
+    fout.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/tests.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,19 @@
+
+
+def test_save_to_pdf():
+    """
+    >>> from .pdf import save_invoice
+    >>> from django.db.models.loading import get_model
+    >>> userModel =  get_model('auth', 'user')
+    >>> user = userModel(username='joe', email='joe@gmail.com',
+    ...         first_name='Joe', last_name='Bloggs')
+    >>> user.save()
+    >>> regModel =  get_model('registration', 'registration')
+    >>> registration = regModel(registrant=user, amount=40,
+    ...          slug='NZPYCON-0001')
+    >>> registration.save()
+
+    >>> save_invoice(user, registration, 'registration/invoice.html')
+
+    """
+    pass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/utils.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+# django
+from django.core.mail import EmailMessage
+
+def send_confirmation(registrant, invoice, password=None, sponsor=None,
+        amount=None):
+
+    message = EmailMessage()
+    message.subject = u'Registration to SciPy.in 2009'
+    message.from_email = u'admin@scipy.in'
+    message.to = [registrant.email]
+    name = '%s %s' % (registrant.first_name, registrant.last_name)
+    if name.strip() == '':
+        name = registrant.username
+
+    username = registrant.username
+    all = {'name': name,
+            'password': password,
+            'username': username}
+
+    if password:
+        message.body = confirmation_newuser % all
+    else:
+        message.body = confirmation_currentuser % all
+
+    message.send()
+
+def send_confirmation_payment_email(registrant):
+    message = EmailMessage()
+    message.subject = u'Registration payment to SciPy.in 2009'
+    message.from_email = u'admin@scipy.in'
+    message.to = [registrant.email]
+    name = '%s %s' % (registrant.first_name, registrant.last_name)
+    username = registrant.username
+    if name.strip() == '':
+        name = registrant.username
+    message.body = confirmation_payment % dict(name=name,
+            username=username)
+    message.send()
+
+def send_banking_fix_email(registrant, invoicenum):
+    message = EmailMessage()
+    message.subject = u'Registration invoice update to SciPy.in 2009'
+    message.from_email = u'admin@scipy.in'
+    message.to = [registrant.email]
+    name = '%s %s' % (registrant.first_name, registrant.last_name)
+    username = registrant.username
+    if name.strip() == '':
+        name = registrant.username
+    message.body = banking_fix % dict(name=name,
+            username=username, invoice=invoicenum)
+    message.send()
+
+banking_fix = """
+Dear %(name)s,
+
+Invoice update to Kiwi Pycon 2009.
+
+Ooops. We made the invoice number too long to be entered for internet banking.
+We have therefore changed the prefix and your new invoice number is:
+%(invoice)s
+
+You will find that your online invoice has been updated. Thanks for your
+patience.
+
+http://nz.pycon.org/invoice
+A pdf version here:
+http://nz.pycon.org/pdf_invoice
+
+Regards,
+The Kiwi Pycon 2009 Team
+
+Your username, in case you've forgotten: %(username)s.
+
+If you have lost your password to the website please visit:
+http://nz.pycon.org/password-reset
+
+    """
+
+confirmation_payment = """
+Dear %(name)s,
+
+Welcome to Kiwi Pycon 2009.
+
+Your payment has been received and your attendence confirmed.
+
+Many thanks!
+
+You can view your invoice at:
+http://nz.pycon.org/invoice
+And a pdf version here:
+http://nz.pycon.org/pdf_invoice
+
+Regards,
+The Kiwi Pycon 2009 Team
+
+Your username, in case you've forgotten: %(username)s.
+
+If you have lost your password to the website please visit:
+http://nz.pycon.org/password-reset
+
+    """
+
+confirmation_newuser = """
+Dear %(name)s,
+
+Welcome to SciPy.in 2009. You may log in to 
+http://scipy.in/login using the following credentials:
+
+Username: %(username)s
+Password: %(password)s
+
+There is an entry fee for the SciPy conference only. However
+the sprint and tutorials don't have any entry fee. The entry
+fee for the conference can be paid on the spot on the first
+day of the conference.
+
+Thanks for your registration!
+
+Regards,
+The SciPy.in Team
+
+If you lose your password to the website please visit:
+http://scipy.in/password-reset
+    """
+
+confirmation_sponsoreduser = """
+Dear %(name)s,
+
+Welcome to Kiwi Pycon 2009.
+
+Your username is: %(username)s
+
+Your registration has been accepted as a guest of %(stype)s 
+sponsor %(sname)s.
+
+Thanks!
+
+Regards,
+The Kiwi Pycon 2009 Team
+
+If you have lost your password to the website please visit:
+http://nz.pycon.org/password-reset
+
+    """
+
+confirmation_sponsorednewuser = """
+Dear %(name)s,
+
+Welcome to Kiwi Pycon 2009.
+
+Your username is: %(username)s
+Your password is: %(password)s
+
+Your registration has been accepted as a guest of %(stype)s sponsor %(sname)s.
+
+Thanks!
+
+Regards,
+The Kiwi Pycon 2009 Team
+
+If you lose your password to the website please visit:
+http://nz.pycon.org/password-reset
+
+    """
+
+confirmation_currentuser = """
+Dear %(name)s,
+
+Welcome to SciPy.in 2009. You may log in to 
+http://scipy.in/login using the following credentials:
+
+Username: %(username)s
+Password: %(password)s
+
+There is an entry fee for the SciPy conference only. However
+the sprint and tutorials don't have any entry fee. The entry
+fee for the conference can be paid on the spot on the first
+day of the conference. 
+
+Thanks for your registration!
+
+Regards,
+The SciPy.in Team
+
+If you lose your password to the website please visit:
+http://scipy.in/password-reset
+    """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/registration/views.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,336 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import cStringIO as StringIO
+import csv
+
+# django
+from django.conf import settings
+from django.shortcuts import render_to_response
+from django.template.loader import render_to_string
+from django.shortcuts import get_object_or_404
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.http import HttpResponse
+
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.forms import AuthenticationForm
+from django.contrib.auth.models import User
+from django.core.exceptions import ObjectDoesNotExist
+
+#kiwipycon
+from project.kiwipycon.utils import set_message_cookie
+from project.kiwipycon.utils import slugify
+from project.kiwipycon.user.models import UserProfile
+from project.kiwipycon.user.utils import kiwipycon_createregistrant
+from project.kiwipycon.user.forms import RegistrantForm
+from project.kiwipycon.sponsor.models import Sponsor
+from project.kiwipycon.talk.models import Talk
+
+from .models import Registration
+from .models import Wifi
+from .forms import RegistrationSubmitForm
+from .forms import RegistrationEditForm
+from .forms import RegistrationAdminSelectForm
+from .forms import WifiForm
+from .utils import send_confirmation
+
+from .forms import IC
+
+REG_TOTAL = 1000
+
+@login_required
+def download_csv(request,
+        template_name = 'registration/download-csv.html'):
+    """
+    """
+    if not request.user.is_staff:
+        redirect_to = reverse('kiwipycon_login')
+    if request.method == "POST":
+        form = RegistrationAdminSelectForm(request.POST)
+        if form.is_valid():
+            conference = form.cleaned_data['by_conference']
+            tutorial = form.cleaned_data['by_tutorial']
+            sprint = form.cleaned_data['by_sprint']
+            amount = form.cleaned_data['by_amount']
+            tshirt = form.cleaned_data['by_tshirt']
+            order_by = form.cleaned_data['order_by']
+            include = form.cleaned_data['include']
+            q = Registration.objects.all()
+            if conference == 'conference':
+                q = q.filter(conference=True)
+            elif conference == 'no conference':
+                q = q.filter(conference=False)
+            elif tutorial == 'tutorial':
+                q = q.filter(tutorial=True)
+            elif tutorial == 'no tutorial':
+                q = q.filter(tutorial=False)
+            if sprint == 'sprint':
+                q = q.filter(sprint=True)
+            if sprint == 'no sprint':
+                q = q.filter(sprint=False)
+            elif tshirt != 'all':
+                q = q.filter(tshirt=tshirt)
+            q = q.order_by('registrant__email')
+            query = q.query
+            results = list(q)
+            if include == []:
+                # default to include all fields
+                include = [i[0] for i in IC]
+            if results:
+                response = HttpResponse(mimetype='text/csv')
+                response['Content-Disposition'] = 'attachment; filename=registrations.csv'
+                output = csv.writer(response)
+                output.writerow([h for h in include])
+                for row in results:
+                    conference = row.conference == True and 'yes' or 'no'
+                    tutorial = row.tutorial == True and 'yes' or 'no'
+                    sprint = row.sprint == True and 'yes' or 'no'
+                    wrow = []
+                    if 'Name' in include:
+                        wrow.append(
+                            row.registrant.get_full_name().encode('utf-8'))
+                    if 'Email' in include:
+                        wrow.append(row.registrant.email.encode('utf-8'))
+                    if 'Organisation' in include:
+                        wrow.append(row.organisation.encode('utf-8'))
+                    if 'Conference' in include:
+                        wrow.append(conference)
+                    if 'Tutorial' in include:
+                        wrow.append(tutorial)
+                    if 'Sprint' in include:
+                        wrow.append(sprint)
+                    if 'T-size' in include:
+                        wrow.append(row.tshirt)
+                    output.writerow(wrow)
+                return response
+            else:
+                no_results = u'No results found for the query'
+
+    else:
+        form = RegistrationAdminSelectForm()
+    return render_to_response(template_name, RequestContext(request,
+        locals()))
+
+# NOT REQUIRED FOR SciPy.in
+@login_required
+def invoice(request, template_name='registration/invoice.html'):
+    user = request.user
+    registration = get_object_or_404(Registration, registrant=user)
+    if registration.sponsor:
+        redirect_to = reverse('kiwipycon_account')
+        return set_message_cookie(redirect_to,
+                msg = u'You are a sponsored guest, no payment required.')
+    return render_to_response(template_name, RequestContext(request,
+        {'registration' : registration, 'user': user}))
+
+@login_required
+def pdf_invoice(request, template_name='registration/invoice.html'):
+    user = request.user
+    registration = get_object_or_404(Registration, registrant=user)
+    if registration.sponsor:
+        redirect_to = reverse('kiwipycon_account')
+        return set_message_cookie(redirect_to,
+                msg = u'You are a sponsored guest, no payment required.')
+    content = render_to_string(template_name,
+        {'registration' : registration, 'user': user})
+    result = StringIO.StringIO()
+    import ho.pisa
+    pdf = ho.pisa.pisaDocument(StringIO.StringIO(content.encode("UTF-8")),result)
+    if not pdf.err:
+        return HttpResponse(result.getvalue(), mimetype='application/pdf')
+    return HttpResponse("Gremlins ate your invoice, please try html" \
+        " version")
+
+
+def registrations(request,
+        template_name='registration/registrations.html'):
+    """Simple page to count registrations"""
+    #registrations = Registration.objects.filter(payment=True).count()
+    registrations = Registration.objects.all().count()
+    return render_to_response(template_name, RequestContext(request,
+        {
+        'over_reg' : registrations >= REG_TOTAL and True or False,
+            'registrations' : registrations}))
+
+@login_required
+def edit_registration(request, id,
+        template_name='registration/edit-registration.html'):
+    '''Allows users that submitted a registration to edit it.
+    '''
+    reg = Registration.objects.get(pk=id)
+
+    if reg.registrant != request.user:
+        redirect_to = reverse('kiwipycon_account')
+        return set_message_cookie(redirect_to,
+                msg = u'Redirected because the registration you selected' \
+                      + ' is not your own.')
+
+    if request.method == 'POST':
+        form = RegistrationEditForm(data=request.POST)
+        if form.is_valid():
+            reg.organisation = form.data.get('organisation')
+            reg.occupation = form.data.get('occupation')
+            reg.city = form.data.get('city')
+            reg.tshirt = form.data.get('tshirt')
+            reg.allow_contact = form.data.get('allow_contact') and True or False
+            reg.conference = form.data.get('conference') and True or False
+            reg.tutorial = form.data.get('tutorial') and True or False
+            reg.sprint = form.data.get('sprint') and True or False
+            reg.save()
+            # Saved.. redirect
+            redirect_to = reverse('kiwipycon_account')
+            return set_message_cookie(redirect_to,
+                    msg = u'Your changes have been saved.')
+    else:
+        form = RegistrationEditForm(initial={
+                                    'id' : id,
+                                    'organisation' : reg.organisation,
+                                    'occupation' : reg.occupation,
+                                    'city' : reg.city,
+                                    'tshirt' : reg.tshirt,
+                                    'conference': reg.conference,
+                                    'tutorial': reg.tutorial,
+                                    'postcode' : reg.postcode,
+                                    'sprint' : reg.sprint,
+                                    'allow_contact' : reg.allow_contact,
+            })
+
+    return render_to_response(template_name, RequestContext(request, locals()))
+
+def submit_registration(request,
+        template_name='registration/submit-registration.html'):
+    '''Allows user to edit registration
+    '''
+    user = request.user
+    reg_count = Registration.objects.all().count()
+    if user.is_authenticated():
+        try:
+            profile = user.get_profile()
+        except:
+            profile, new = UserProfile.objects.get_or_create(user=user)
+            if new:
+                profile.save()
+        try:
+            registration = Registration.objects.get(registrant=user)
+            if registration:
+                redirect_to = reverse('kiwipycon_account')
+                return set_message_cookie(redirect_to,
+                        msg = u'You have already been registered.')
+
+        except ObjectDoesNotExist:
+            pass
+
+    message = None
+
+    if request.method == 'POST':
+        registration_form = RegistrationSubmitForm(data=request.POST)
+        registrant_form = RegistrantForm(data=request.POST)
+        wifi_form = WifiForm(data=request.POST)
+
+        if request.POST.get('action', None) == 'login':
+            login_form = AuthenticationForm(data=request.POST)
+            if login_form.is_valid():
+
+                from django.contrib.auth import login
+                login(request, login_form.get_user())
+
+                redirect_to = reverse('kiwipycon_submit_registration')
+                return set_message_cookie(redirect_to,
+                        msg = u'You have been logged in please continue' + \
+                               'with registration.')
+
+        newuser = None
+        passwd = None
+        if not user.is_authenticated():
+            if registrant_form.is_valid():
+                newuser = kiwipycon_createregistrant(request, registrant_form.data)
+                # Log in user
+                passwd = User.objects.make_random_password()
+                newuser.set_password(passwd)
+                newuser.save()
+                from django.contrib.auth import authenticate
+                user = authenticate(username=newuser.username, password=passwd)
+
+                from django.contrib.auth import login
+                login(request, user)
+
+                newuser = user
+
+        else:
+            newuser = user
+
+        if registration_form.is_valid() and newuser:
+            allow_contact = registration_form.data.get('allow_contact') and \
+                                        True or False
+            conference = registration_form.data.get('conference') and \
+                                        True or False
+            tutorial = registration_form.data.get('tutorial') and \
+                                        True or False
+            sprint = registration_form.data.get('sprint') and \
+                                        True or False
+
+            registrant = User.objects.get(pk=newuser.id)
+
+            presenter = None
+            talks = Talk.objects.filter(
+                    speaker=registrant).filter(approved=True)
+            if talks:
+                for talk in talks:
+                    if talk.duration == '30':
+                        presenter = True
+                    elif talk.duration == '60':
+                        presenter = True
+            
+            reg = Registration(
+                    #     slug = newuser.username,
+                registrant = registrant,
+                organisation = registration_form.data.get('organisation'),
+                occupation = registration_form.data.get('occupation'),
+                city = registration_form.data.get('city'),
+                tshirt = registration_form.data.get('tshirt'),
+                postcode = registration_form.cleaned_data.get('postcode'),
+                allow_contact = allow_contact,
+                conference = conference,
+                tutorial = tutorial,
+                sprint = sprint)
+            reg.save() 
+
+            # get id and use as slug and invoice number
+            id = reg.id
+            slug = 'KPC09%03d' % id
+            reg.slug = slug
+            reg.save()
+
+            # additional tasks:
+            if wifi_form.is_valid():
+                wifi = wifi_form.save(registrant)
+            
+            # 1. include random password if we are a new user
+            if passwd:
+                send_confirmation(registrant, slug, password=passwd)
+            else:
+            # 2. send user email with registration id
+                send_confirmation(registrant, slug)
+
+            redirect_to = reverse('kiwipycon_registrations')
+            return set_message_cookie(redirect_to,
+                    msg = u'Thank you, your registration has been submitted '\
+                           'and an email has been sent with payment details.')
+
+    else:
+        registration_form = RegistrationSubmitForm()
+        registrant_form = RegistrantForm()
+        wifi_form = WifiForm()
+
+    login_form = AuthenticationForm()
+
+
+    return render_to_response(template_name, RequestContext(request, {
+        'registration_form': registration_form,
+        'registrant_form' : registrant_form,
+        'over_reg' : reg_count >= REG_TOTAL and True or False,
+        'wifi_form' : wifi_form,
+        'message' : message,
+        'login_form' : login_form
+    }))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/sponsor/admin.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django.contrib import admin
+
+#kiwipycon
+from .models import Sponsor
+
+class SponsorAdmin(admin.ModelAdmin):
+    list_display = ('title', 'type', 'contact_name', 'contact_email', 'contact_phone',
+            'guests', 'url', 'logo')
+
+admin.site.register(Sponsor, SponsorAdmin)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/sponsor/migrations/0001_initial.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+
+from south.db import db
+from django.db import models
+from project.kiwipycon.sponsor.models import *
+
+class Migration:
+    
+    def forwards(self, orm):
+        
+        # Adding model 'Sponsor'
+        db.create_table('sponsor_sponsor', (
+            ('id', models.AutoField(primary_key=True)),
+            ('slug', models.SlugField()),
+            ('title', models.CharField(max_length=255)),
+            ('type', models.CharField(max_length=10)),
+            ('url', models.URLField(verify_exists=False, blank=True)),
+            ('contact_name', models.CharField(max_length=255)),
+            ('contact_phone', models.CharField(max_length=255)),
+            ('contact_email', models.CharField(max_length=255)),
+            ('logo', models.CharField(max_length=64, blank=True)),
+            ('guests', models.IntegerField()),
+        ))
+        db.send_create_signal('sponsor', ['Sponsor'])
+        
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'Sponsor'
+        db.delete_table('sponsor_sponsor')
+        
+    
+    
+    models = {
+        'sponsor.sponsor': {
+            'contact_email': ('models.CharField', [], {'max_length': '255'}),
+            'contact_name': ('models.CharField', [], {'max_length': '255'}),
+            'contact_phone': ('models.CharField', [], {'max_length': '255'}),
+            'guests': ('models.IntegerField', [], {}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'logo': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}),
+            'slug': ('models.SlugField', [], {}),
+            'title': ('models.CharField', [], {'max_length': '255'}),
+            'type': ('models.CharField', [], {'max_length': '10'}),
+            'url': ('models.URLField', [], {'verify_exists': 'False', 'blank': 'True'})
+        }
+    }
+    
+    complete_apps = ['sponsor']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/sponsor/models.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django.db import models
+from django.conf import settings
+
+TYPE_CHOICES = (
+    ('gold', 'Gold'),
+    ('silver', 'Silver'),
+    ('schwag', 'Schwag'),
+    )
+
+class Sponsor(models.Model):
+    """Defines sponsors for *PyCon"""
+    slug = models.SlugField()
+    title = models.CharField(max_length=255)
+    type = models.CharField(max_length=10, choices=TYPE_CHOICES)
+    contact_name = models.CharField(max_length=255)
+    contact_email = models.CharField(max_length=255)
+    contact_phone = models.CharField(max_length=255)
+    url = models.URLField(blank=True, verify_exists=False)
+    logo = models.CharField(max_length=64, blank=True)
+    guests = models.IntegerField()
+
+    def __unicode__(self):
+        return self.title
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/sponsor/views.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+# django
+from django.conf import settings
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+
+def schwag_sponsors(request,
+        template_name = 'sponsor/schwag.html'):
+    """Simple page to display schwag sponsors
+    
+    The list is generated in kiwipycon.context_processors
+    """
+    return render_to_response(template_name, RequestContext(request,
+        {}))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/admin.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django.contrib
+from django.contrib import admin
+
+#kiwipycon
+from .models import Talk
+
+class TalkAdmin(admin.ModelAdmin):
+    list_display = ('title', 'speaker', 'topic', 'duration', 'audience', 'approved')
+    list_filter = ('approved', 'audience', 'topic', 'speaker')
+    search_fields = ('slug', 'title', 'abstract')
+    prepopulate_from = {'slug': ('title',)}
+    fieldsets = (
+        ('Details', {
+            'fields': ('slug', 'title', 'abstract', 'speaker')
+        }),
+        ('Information', {
+            'fields': ('topic', 'duration', 'audience', 'approved')
+        }),
+    )
+admin.site.register(Talk, TalkAdmin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/forms.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django import forms
+
+#django.contrib
+from django.contrib.auth.models import User
+
+#tagging
+from tagging.forms import TagField
+
+#kiwipycon
+#from .models import TOPIC_CHOICES
+from .models import DURATION_CHOICES
+from .models import AUDIENCE_CHOICES
+
+
+class TalkSubmitForm(forms.Form):
+    """Submit talk form
+    """
+    authors_bio = forms.CharField(widget=forms.Textarea, required=True,
+        label=u'Author(s) and short bio',
+        help_text=u'(include a bit about your qualifications regarding your presentation topic)')
+    contact = forms.EmailField(required=True, label=u'E-Mail ID',
+        help_text=u'Provide your email ID',
+        max_length=1024,
+        widget=forms.TextInput(attrs={'size':'50'}))
+    title = forms.CharField(required=True, label=u'Talk title',
+        help_text=u'Title of proposed presentation',
+        max_length=1024,
+        widget=forms.TextInput(attrs={'size':'50'}))
+    abstract = forms.CharField(widget=forms.Textarea, required=True,
+        help_text=u'Summary of proposed presentation (In 300-700 words)')
+#    outline = forms.CharField(widget=forms.Textarea, required=True,
+#        help_text=u'Outline of proposed presentation (around 200 words)')
+#    topic = forms.ChoiceField(choices=TOPIC_CHOICES,
+#        label=u'Topic', help_text=u'Select one of the available options or enter other topic')
+#    topic_other = forms.CharField(label=u'Other topic',
+#        help_text=u'Description of your topic',
+#        max_length=255,
+#        required=False,
+#        widget=forms.TextInput(attrs={'size':'50'}))
+    topic = forms.CharField(label=u'Topic',
+        help_text=u'Description of your topic or comma separated tags',
+        max_length=255,
+        required=False,
+        widget=forms.TextInput(attrs={'size':'50'}))
+    duration = forms.ChoiceField(choices=DURATION_CHOICES, required=True,
+        label=u'Preferred timeslot', help_text=u'Select preferred time slot')
+    audience = forms.ChoiceField(choices=AUDIENCE_CHOICES, label=u'Intended audience',
+        help_text=u'Select one of the available options or enter other type of intended audience')
+#    audience_other = forms.CharField(label=u'Other intended audience',
+#        help_text=u'Description of intended audience (ie. Discordians)',
+#        max_length=128,
+#        required=False,
+#        widget=forms.TextInput(attrs={'size':'50'}))
+#    tags = TagField(max_length=255,
+#        widget=forms.TextInput(attrs={'size':'50'}))
+
+class TalkEditForm(TalkSubmitForm):
+    id = forms.CharField(widget=forms.HiddenInput)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/migrations/0001_initial.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+
+from south.db import db
+from django.db import models
+from project.kiwipycon.talk.models import *
+
+class Migration:
+    
+    def forwards(self, orm):
+        
+        # Adding model 'Talk'
+        db.create_table('talk_talk', (
+            ('id', models.AutoField(primary_key=True)),
+            ('slug', models.SlugField()),
+            ('speaker', models.ForeignKey(orm['auth.User'])),
+            ('authors_bio', models.TextField()),
+            ('contact', models.CharField(max_length=1024)),
+            ('title', models.CharField(max_length=1024)),
+            ('abstract', models.TextField()),
+#            ('outline', models.TextField()),
+            ('topic', models.CharField(blank=True, max_length=255)),
+#            ('topic_other', models.CharField(max_length=255, blank=True)),
+            ('duration', models.CharField(max_length=3)),
+            ('audience', models.CharField(blank=True, max_length=32)),
+#            ('audience_other', models.CharField(max_length=128, blank=True)),
+            ('approved', models.BooleanField(default=False)),
+            ('submitted', models.DateTimeField(auto_now_add=True)),
+            ('last_mod', models.DateTimeField(auto_now=True)),
+#            ('tags', TagField(blank=True)),
+        ))
+        db.send_create_signal('talk', ['Talk'])
+        
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'Talk'
+        db.delete_table('talk_talk')
+        
+    
+    
+    models = {
+        'auth.user': {
+            '_stub': True,
+            'id': ('models.AutoField', [], {'primary_key': 'True'})
+        },
+        'talk.talk': {
+            'abstract': ('models.TextField', [], {}),
+            'approved': ('models.BooleanField', [], {'default': 'False'}),
+            'audience': ('models.CharField', [], {'blank': 'True', 'max_length': '32'}),
+            'audience_other': ('models.CharField', [], {'max_length': '128', 'blank': 'True'}),
+            'authors_bio': ('models.TextField', [], {}),
+            'contact': ('models.CharField', [], {'max_length': '1024'}),
+            'duration': ('models.CharField', [], {'max_length': '3'}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'last_mod': ('models.DateTimeField', [], {'auto_now': 'True'}),
+            'outline': ('models.TextField', [], {}),
+            'slug': ('models.SlugField', [], {}),
+            'speaker': ('models.ForeignKey', ['User'], {}),
+            'submitted': ('models.DateTimeField', [], {'auto_now_add': 'True'}),
+            'tags': ('TagField', [], {'blank': 'True'}),
+            'title': ('models.CharField', [], {'max_length': '1024'}),
+            'topic': ('models.CharField', [], {'blank': 'True', 'max_length': '255'}),
+            'topic_other': ('models.CharField', [], {'max_length': '255', 'blank': 'True'})
+        }
+    }
+    
+    complete_apps = ['talk']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/models.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django.db import models
+from django.contrib.auth.models import User
+
+#tagging
+from tagging import register
+from tagging.fields import TagField
+from tagging.utils import parse_tag_input
+
+DURATION_CHOICES = (
+    ('10', 'Lightning Talk (10 mins)'),
+    ('20', 'Short Talk (20 mins)'),
+    ('30', 'Standard Talk (30 mins)'),
+    )
+
+AUDIENCE_CHOICES = (
+    ('nonprogrammers', 'non-programmer'),
+    ('beginers', 'beginning programmer'),
+    ('intermediate', 'intermediate programmer'),
+    ('advanced', 'advanced programmer'),
+    )
+
+#TOPIC_CHOICES = (
+#    ('Core Python', 'Core Python'),
+#    ('Other implementations: Jython, IronPython, PyPy, and Stackless', 'Other implementations: Jython, IronPython, PyPy, and Stackless'),
+#    ('Python libraries and extensions', 'Python libraries and extensions'),
+#    ('Python 3k', 'Python 3k'),
+#    ('Databases', 'Databases'),
+#    ('Documentation', 'Documentation'),
+#    ('GUI Programming', 'GUI Programming'),
+#    ('Game Programming', 'Game Programming'),
+#    ('Network Programming', 'Network Programming'),
+#    ('Open Source Python projects', 'Open Source Python projects'),
+#    ('Packaging Issues', 'Packaging Issues'),
+#    ('Programming Tools', 'Programming Tools'),
+#    ('Project Best Practices', 'Project Best Practices'),
+#    ('Embedding and Extending', 'Embedding and Extending'),
+#    ('Science and Maths', 'Science and Maths'),
+#    ('Web-based Systems', 'Web-based Systems'),
+#)
+
+class Talk(models.Model):
+    """Defines talks at *PyCon"""
+    slug = models.SlugField()
+    speaker = models.ForeignKey(User)
+    authors_bio = models.TextField()
+    contact = models.EmailField()
+    title = models.CharField(max_length=1024)
+    abstract = models.TextField()
+#    outline = models.TextField()
+    topic = models.CharField(max_length=255, 
+                             #choices=TOPIC_CHOICES,
+                             blank=True)
+#    topic_other = models.CharField(max_length=255, blank=True)
+    duration = models.CharField(max_length=3, choices=DURATION_CHOICES)
+    audience = models.CharField(max_length=32, choices=AUDIENCE_CHOICES, blank=True)
+#    audience_other = models.CharField(max_length=128, blank=True)
+    approved = models.BooleanField(default=False)
+    submitted = models.DateTimeField(auto_now_add=True)
+    last_mod = models.DateTimeField(auto_now=True)
+#    tags = TagField(blank=True)
+
+    def __unicode__(self):
+        return self.title
+
+    def get_tag_list(self):
+        return parse_tag_input(self.tags)
+
+# register(Talk) # saving talk failed - see:
+# http://code.google.com/p/django-tagging/issues/detail?id=152
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/templatetags/__init__.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,1 @@
+#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/templatetags/talk_extras.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,8 @@
+from django import template
+
+register = template.Library()
+
+def choice(choices, value):
+    return choices[value]
+
+register.filter('choice', choice)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/talk/views.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,193 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+# python imports
+from urlparse import urlparse
+
+# django
+from django.conf import settings
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.views.generic.list_detail import object_list
+from django.views.generic.list_detail import object_detail
+
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.forms import AuthenticationForm
+from django.contrib.auth.models import User
+
+# PIL
+from PIL import Image
+
+# tagging
+from tagging.models import Tag
+
+#kiwipycon
+from project.kiwipycon.utils import set_message_cookie
+from project.kiwipycon.utils import slugify
+from project.kiwipycon.user.models import UserProfile
+from project.kiwipycon.user.forms import RegisterForm
+from project.kiwipycon.user.utils import kiwipycon_createuser
+
+from .models import Talk
+from .forms import TalkSubmitForm
+from .forms import TalkEditForm
+from .models import DURATION_CHOICES
+from .models import AUDIENCE_CHOICES
+
+def list_talks(request):
+    objects = Talk.objects.filter(approved=True)
+    extra_context = dict(count=objects.count())
+    return object_list(request, objects, extra_context=extra_context)
+
+def talk(request, id):
+    objects = Talk.objects.filter(approved=True)
+    audience = {}
+    for choice in AUDIENCE_CHOICES:
+        audience[choice[0]] = choice[1]
+    extra_context = dict(choices=audience)
+    return object_detail(request, objects, id, extra_context=extra_context)
+
+@login_required
+def edit_talk(request, id, template_name='talk/edit-talk.html'):
+    '''Allows users that submitted a talk to edit it until the talk is approved.
+    '''
+    talk = Talk.objects.get(pk=id)
+
+    if talk.approved == True:
+        redirect_to = reverse('kiwipycon_account')
+        return set_message_cookie(redirect_to,
+                msg = u'Sorry but you cannot edit the talk once'\
+                      + ' it has been accepted.')
+    if talk.speaker != request.user:
+        redirect_to = reverse('kiwipycon_account')
+        return set_message_cookie(redirect_to,
+                msg = u'Redirected to account because the talk you selected' \
+                      + ' is not your own.')
+
+    if request.method == 'POST':
+        form = TalkEditForm(data=request.POST)
+        if form.is_valid():
+            talk.slug = slugify(form.data.get('title'))
+            talk.authors_bio = form.data.get('authors_bio')
+            talk.contact = form.data.get('contact')
+            talk.title = form.data.get('title')
+            talk.abstract = form.data.get('abstract')
+#            talk.outline = form.data.get('outline')
+            talk.topic = form.data.get('topic')
+#            talk.topic_other = form.data.get('topic_other')
+            talk.duration = form.data.get('duration')
+            talk.audience = form.data.get('audience')
+#            talk.audience_other = form.data.get('audience_other')
+#            talk.tags = form.data.get('tags')
+            talk.save()
+            # Saved.. redirect
+            redirect_to = reverse('kiwipycon_account')
+            return set_message_cookie(redirect_to,
+                    msg = u'Your changes have been saved.')
+    else:
+        form = TalkEditForm(initial={
+                                    'id' : id,
+                                    'authors_bio' : talk.authors_bio,
+                                    'contact' : talk.contact,
+                                    'title' : talk.title,
+                                    'abstract' : talk.abstract,
+#                                    'outline' : talk.outline,
+                                    'topic' : talk.topic,
+#                                    'topic_other' : talk.topic_other,
+                                    'duration' : talk.duration,
+                                    'audience' : talk.audience,
+#                                    'audience_other' : talk.audience_other,
+#                                    'tags' : talk.tags,
+            })
+
+    return render_to_response(template_name, RequestContext(request, locals()))
+
+@login_required()
+def submit_talk(request, template_name='talk/submit-talk.html'):
+    '''Allows user to edit profile
+    '''
+    user = request.user
+    if user.is_authenticated():
+        try:
+            profile = user.get_profile()
+        except:
+            profile, new = UserProfile.objects.get_or_create(user=user)
+            if new:
+                profile.save()
+    message = None
+
+    if request.method == 'POST':
+        talk_form = TalkSubmitForm(data=request.POST)
+
+        register_form = RegisterForm(data=request.POST,
+                                        files=request.FILES)
+
+        if request.POST.get('action', None) == 'login':
+            login_form = AuthenticationForm(data=request.POST)
+            if login_form.is_valid():
+
+                from django.contrib.auth import login
+                login(request, login_form.get_user())
+
+                redirect_to = reverse('kiwipycon_submit_talk')
+                return set_message_cookie(redirect_to,
+                        msg = u'You have been logged in.')
+
+        if request.POST.get('action', None) == 'register':
+            # add the new user
+            if register_form.is_valid():
+
+                user = kiwipycon_createuser(request, register_form.data)
+
+        if talk_form.is_valid():
+            if user.is_authenticated():
+                title = talk_form.data.get('title')
+                talk = Talk.objects.create(
+                    slug = slugify(title),
+                    speaker = User.objects.get(pk=user.id),
+                    authors_bio = talk_form.data.get('authors_bio'),
+                    contact = talk_form.data.get('contact'),
+                    title = talk_form.data.get('title'),
+                    abstract = talk_form.data.get('abstract'),
+#                    outline = talk_form.data.get('outline'),
+                    topic = talk_form.data.get('topic'),
+#                    topic_other = talk_form.data.get('topic_other'),
+                    duration = talk_form.data.get('duration'),
+                    audience = talk_form.data.get('audience'),
+#                    audience_other = talk_form.data.get('audience_other'),
+                    approved = False,
+#                    tags = talk_form.data.get('tags')
+                    )
+                talk.save()
+                # Saved, ... redirect back to account
+                redirect_to = reverse('kiwipycon_account')
+                return set_message_cookie(redirect_to,
+                        msg = u'Thanks, your talk has been submitted.')
+            else:
+                redirect_to = reverse('kiwipycon_submit_talk')
+                return set_message_cookie(redirect_to,
+                        msg = u'Something is wrong here.')
+
+    else:
+        talk_form = TalkSubmitForm()
+        register_form = RegisterForm()
+    login_form = AuthenticationForm()
+
+
+    return render_to_response(template_name, RequestContext(request, {
+        'talk_form': talk_form,
+        'register_form' : register_form,
+        'message' : message,
+        'login_form' : login_form
+    }))
+
+def list_talks(request, template_name='talk/list-all-talks.html'):
+    '''List all the tasks submitted by a user.
+    '''
+
+    talks = Talk.objects.filter(approved=True)
+
+    return render_to_response(template_name, RequestContext(request, {
+        'talk_list': talks,
+    }))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/user/admin.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django.contrib import admin
+
+#kiwipycon
+from .models import UserProfile
+
+class UserProfileAdmin(admin.ModelAdmin):
+    list_display = ('user', 'email',  'url', 'about')
+
+    def email(self, obj):
+        return obj.user.email
+
+admin.site.register(UserProfile, UserProfileAdmin)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/user/forms.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django import forms
+from django.contrib.auth.models import User
+
+class RegistrantForm(forms.Form):
+    """Form to register an attendee
+    """
+    username = forms.RegexField(label="Nickname", max_length=30,
+            regex=r'^\w+$',
+        help_text = "30 characters or fewer. Alphanumeric" \
+            + " characters only (letters, digits and underscores).",
+        error_message = "This value must contain only letters, numbers and underscores.")
+    name = forms.CharField(label=u"Name", max_length=50, required=True)
+    email = forms.EmailField(label=u"E-mail", max_length=50, required=True)
+
+    def clean_email(self):
+        """Validates that the entered e-mail is unique.
+        """
+        email = self.cleaned_data.get("email")
+        if email and User.objects.filter(email=email).count() > 0:
+            raise forms.ValidationError(
+                u"That email address is already in use. Are you a member of " \
+                 "site? Please log in.")
+
+        return email
+
+    def clean_username(self):
+        """Validates that the entered username is unique.
+        """
+        username = self.cleaned_data.get("username")
+        if username and User.objects.filter(username=username).count() > 0:
+            raise forms.ValidationError(
+                u"That username is already in use.")
+
+        return username
+
+class RegisterForm(forms.Form):
+    """Form to register speaker
+    """
+    username = forms.RegexField(label="Username", max_length=30,
+            regex=r'^\w+$',
+        help_text = "Required. 30 characters or fewer. Alphanumeric" \
+            + " characters only (letters, digits and underscores).",
+        error_message = "This value must contain only letters, numbers and underscores.")
+    first_name = forms.CharField(label=u"First name", max_length=50)
+    last_name = forms.CharField(label=u"Last name", max_length=50)
+    email = forms.EmailField(label=u"E-mail", max_length=50)
+    url = forms.URLField(required=False)
+    about = forms.CharField(label=u'Short Bio', max_length=50, required=False)
+    photo = forms.FileField(label=u'Profile Photo', required=False)
+    password_1 = forms.CharField(
+        label=u"Password", widget=forms.PasswordInput(), max_length=20)
+    password_2 = forms.CharField(
+        label=u"Confirm password", widget=forms.PasswordInput(), max_length=20)
+
+    def clean_password_2(self):
+        """Validates that password 1 and password 2 are the same.
+        """
+        p1 = self.cleaned_data.get('password_1')
+        p2 = self.cleaned_data.get('password_2')
+
+        if not (p1 and p2 and p1 == p2):
+            raise forms.ValidationError(u"The two passwords do not match.")
+
+        return p2
+
+    def clean_email(self):
+        """Validates that the entered e-mail is unique.
+        """
+        email = self.cleaned_data.get("email")
+        if email and User.objects.filter(email=email).count() > 0:
+            raise forms.ValidationError(
+                u"That email address is already in use.")
+
+        return email
+
+    def clean_username(self):
+        """Validates that the entered username is unique.
+        """
+        username = self.cleaned_data.get("username")
+        if username and User.objects.filter(username=username).count() > 0:
+            raise forms.ValidationError(
+                u"That username is already in use.")
+
+        return username
+
+class EditProfileForm(forms.Form):
+    """Edit user profile form
+    """
+    first_name = forms.CharField(max_length=50)
+    last_name = forms.CharField(max_length=50)
+    email = forms.EmailField(max_length=50)
+    email2 = forms.CharField(widget=forms.HiddenInput)
+    url = forms.URLField(required=False)
+    about = forms.CharField(label=u'Short Bio',
+            widget=forms.Textarea, required=False)
+    photo = forms.FileField(label=u'Profile Photo',
+            required=False)
+
+    def clean_email(self):
+        """Validates that the entered e-mail is unique.
+        """
+        email = self.cleaned_data.get("email")
+        email2 = self.data.get("email2").strip()
+        print email, email2
+        if email != email2: # email has been changed
+            if email and User.objects.filter(email=email).count() > 0:
+                raise forms.ValidationError(
+                    u"That email address is already in use.")
+
+        return email
+
+class UsernameForm(forms.Form):
+    """Form to edit email address
+    """
+    username = forms.RegexField(label="Username", max_length=30,
+            regex=r'^\w+$',
+        help_text = "Required. 30 characters or fewer. Alphanumeric" \
+            + " characters only (letters, digits and underscores).",
+        error_message = "This value must contain only letters, numbers and underscores.")
+
+    def clean_username(self):
+        """Validates that the entered username is unique.
+        """
+        username = self.cleaned_data.get("username")
+        if username and User.objects.filter(username=username).count() > 0:
+            raise forms.ValidationError(
+                u"That username is already in use.")
+
+        return username
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/user/migrations/0001_initial.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+
+from south.db import db
+from django.db import models
+from project.kiwipycon.user.models import *
+
+class Migration:
+    
+    def forwards(self, orm):
+        
+        # Adding model 'UserProfile'
+        db.create_table('user_userprofile', (
+            ('id', models.AutoField(primary_key=True)),
+            ('user', models.ForeignKey(orm['auth.User'], unique=True)),
+            ('url', models.URLField(verify_exists=False, blank=True)),
+            ('photo', models.CharField(max_length=64, blank=True)),
+            ('about', models.TextField(blank=True)),
+        ))
+        db.send_create_signal('user', ['UserProfile'])
+        
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'UserProfile'
+        db.delete_table('user_userprofile')
+        
+    
+    
+    models = {
+        'auth.user': {
+            '_stub': True,
+            'id': ('models.AutoField', [], {'primary_key': 'True'})
+        },
+        'user.userprofile': {
+            'about': ('models.TextField', [], {'blank': 'True'}),
+            'id': ('models.AutoField', [], {'primary_key': 'True'}),
+            'photo': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}),
+            'url': ('models.URLField', [], {'verify_exists': 'False', 'blank': 'True'}),
+            'user': ('models.ForeignKey', ['User'], {'unique': 'True'})
+        }
+    }
+    
+    complete_apps = ['user']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/user/models.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#django
+from django.db import models
+from django.conf import settings
+from django.db.models.signals import post_save
+from django.contrib.auth.models import User
+
+class UserProfile(models.Model):
+    """
+    Extend atributes for django User
+    """
+    user = models.ForeignKey(User, unique=True)
+    url = models.URLField(blank=True, verify_exists=False)
+    photo = models.CharField(max_length=64, blank=True)
+    about = models.TextField(blank=True)
+
+    def __unicode__(self):
+        return 'UserProfile for user: <%s %s> %s' % (self.user.first_name,
+                self.user.last_name, self.user.email)
+
+    def fullname(self):
+        return '%s %s' % (self.user.first_name, self.user.last_name)
+
+def add_profile(sender, instance, signal, *args, **kwargs):
+    """Create user profile on create of new user"""
+    if not instance.is_superuser:
+        try:
+            profile, new = UserProfile.objects.get_or_create(user=instance)
+            if new:
+                profile.save()
+        except:
+            pass
+
+post_save.connect(add_profile, sender=User, weak=False)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/user/utils.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#python imports
+import os
+
+#django
+from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+
+#django.contrib
+from django.contrib.auth.models import User
+
+#PIL
+from PIL import Image
+
+
+def kiwipycon_createregistrant(request, data):
+    """Create user"""
+    email = data.get("email")
+    name = data.get("name")
+    username = data.get("username")
+
+    n = name.split(" ")
+    if len(n) > 1:
+        first_name = ' '.join(n[:-1])
+        last_name = n[-1]
+    else:
+        first_name = ''
+        last_name = n[0]
+
+
+    # Create user
+    user = User.objects.create_user(username=username, email=email)
+    user.first_name = first_name
+    user.last_name = last_name
+    user.save()
+
+    return user
+
+def kiwipycon_createuser(request, data):
+    """Create user"""
+    email = data.get("email")
+    username = data.get("username")
+    password = data.get("password_1")
+    password = data.get("password_1")
+
+    # Create user
+    user = User.objects.create_user(
+        username=username, email=email, password=password)
+    user.first_name = data.get("first_name")
+    user.last_name = data.get("last_name")
+    user.save()
+
+    # Log in user
+    from django.contrib.auth import authenticate
+    user = authenticate(username=username, password=password)
+
+    from django.contrib.auth import login
+    login(request, user)
+
+    profile = user.get_profile()
+    photo = request.FILES.get('photo', None)
+    filename= None
+    if photo:
+        filename = handle_uploaded_photo(user, request.FILES['photo'])
+    if filename:
+        profile.photo = filename
+    #print photo, filename
+
+    profile.url = data.get("url")
+    profile.about = data.get("about")
+    profile.save()
+
+    return user
+
+def handle_uploaded_photo(user, ufile):
+    usermedia = settings.USER_MEDIA_ROOT
+    filename = ufile.name
+    ext = filename.split('.')[-1]
+    filesize = ufile.size
+    filecontent = ufile.read()
+    userfilename = 'user-%d.%s' % (user.id, ext)
+    if not filecontent:
+        return None
+
+    #save
+    foutname = os.path.join(usermedia, userfilename)
+
+    fout = file(foutname, 'wb')
+    fout.write(filecontent)
+    fout.close()
+
+    # crop and resize
+    image = Image.open(foutname)
+    pw = image.size[0]
+    ph = image.size[1]
+    nw = nh = 80
+    if (pw, ph) != (nw, nh):
+        pr = float(pw) / float(ph)
+        nr = float(nw) / float(nh)
+
+        if pr > nr:
+            # photo aspect is wider than destination ratio
+            tw = int(round(nh * pr))
+            image = image.resize((tw, nh), Image.ANTIALIAS)
+            l = int(round(( tw - nw ) / 2.0))
+            image = image.crop((l, 0, l + nw, nh))
+        elif pr < nr:
+            # photo aspect is taller than destination ratio
+            th = int(round(nw / pr))
+            image = image.resize((nw, th), Image.ANTIALIAS)
+            t = int(round(( th - nh ) / 2.0))
+            #print((0, t, nw, t + nh))
+            image = image.crop((0, t, nw, t + nh))
+        else:
+            # photo aspect matches the destination ratio
+            image = image.resize((nw, nh), Image.ANTIALIAS)
+
+        image.save(str(foutname))
+    return userfilename
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/user/views.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,278 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+#python
+from urlparse import urlparse
+import json
+import urllib
+import os
+
+#django
+from django.conf import settings
+from django.db.models import Q
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.db.models.signals import post_save
+
+#django.contrib
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.forms import AuthenticationForm
+from django.contrib.auth.forms import PasswordChangeForm
+from django.contrib.auth.models import User
+from django.core.exceptions import ObjectDoesNotExist
+
+#PIL
+from PIL import Image
+
+#kiwipycon
+from project.kiwipycon.utils import set_message_cookie
+from project.kiwipycon.talk.models import Talk
+from project.kiwipycon.registration.models import Registration
+from project.kiwipycon.registration.models import Wifi
+from project.kiwipycon.registration.forms import WifiForm
+from project.kiwipycon.sponsor.models import Sponsor
+
+from .utils import kiwipycon_createuser
+from .utils import handle_uploaded_photo
+from .forms import RegisterForm
+from .forms import EditProfileForm
+from .forms import UsernameForm
+
+@login_required
+def account(request, template_name="user/account.html"):
+    """Displays the main screen of the current user's account.
+    """
+    user = request.user
+    profile = user.get_profile()
+
+    talks = Talk.objects.filter(speaker=user)
+    try:
+        registration = Registration.objects.get(registrant=user)
+    except ObjectDoesNotExist:
+        registration = None
+    try:
+        wifiobj = Wifi.objects.get(user=user)
+    except ObjectDoesNotExist:
+        wifiobj = None
+
+    if profile.photo:
+        photo = os.path.join(settings.USER_MEDIA_URL, profile.photo)
+    else:
+        photo = '/img/user-default.png'
+
+    qstring = ""
+
+    wifi_comment = None
+    if wifiobj:
+        wifi_form = False
+    else:
+        if request.method == "POST":
+            wifi_form = WifiForm(request.POST)
+            if wifi_form.is_valid():
+                wifi_form.save(user)
+            wifi_comment = 'Thanks, your wifi preference has been saved'
+            wifi_form = None
+        else:
+            wifi_form = WifiForm()
+
+    return render_to_response(template_name, RequestContext(request, {
+        "form" : wifi_form, "comment": wifi_comment,
+        "user" : user, "profile" : profile, "photo" : photo,
+        "talks" : talks, "registration" : registration,
+    }))
+
+@login_required
+def edit_profile(request, template_name="user/editprofile.html"):
+    """Allows user to edit profile
+    """
+    user = request.user
+    profile = user.get_profile()
+
+    if request.method == "POST":
+        form = EditProfileForm(data=request.POST,
+                               files=request.FILES)
+
+        if form.is_valid():
+            photo = request.FILES.get('photo', None)
+            filename= None
+            if photo:
+                filename = handle_uploaded_photo(user, request.FILES['photo'])
+            if filename:
+                profile.photo = filename
+
+            user.email = form.data.get("email")
+            user.first_name = form.data.get("first_name")
+            user.last_name = form.data.get("last_name")
+            user.save()
+
+            profile.url = form.data.get("url")
+            profile.about = form.data.get("about")
+            profile.save()
+
+            redirect_to = reverse("kiwipycon_account")
+            return set_message_cookie(redirect_to,
+                    msg = u"Your profile has been changed.")
+
+    else:
+        form = EditProfileForm(initial={"email" : user.email,
+                                        "email2" : user.email, # hidden field
+                                        "first_name" : user.first_name,
+                                        "last_name" : user.last_name,
+                                        "url" : profile.url,
+                                        "about" : profile.about,
+                                        })
+
+    return render_to_response(template_name, RequestContext(request, {
+        "form": form
+    }))
+
+def login(request, template_name="user/login.html"):
+    """Custom view to login or register/login a user.
+    Integration of register and login form
+    It uses Django's standard AuthenticationForm, though.
+    """
+    user = request.user
+    if user.is_authenticated():
+        redirect_to = reverse("kiwipycon_account")
+        return set_message_cookie(redirect_to,
+                msg = u"Redirected to account from login form.")
+
+    # Using Djangos default AuthenticationForm
+    login_form = AuthenticationForm()
+    register_form = RegisterForm()
+
+    if request.POST.get("action") == "login":
+        login_form = AuthenticationForm(data=request.POST)
+
+        if login_form.is_valid():
+            redirect_to = request.POST.get("next")
+            # Light security check -- make sure redirect_to isn't garbage.
+            if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
+                redirect_to = reverse("kiwipycon_account")
+
+            from django.contrib.auth import login
+            login(request, login_form.get_user())
+
+            return set_message_cookie(redirect_to, msg = u"You have been logged in.")
+
+    elif request.POST.get("action") == "register":
+        register_form = RegisterForm(data=request.POST)
+        if register_form.is_valid():
+
+            user = kiwipycon_createuser(request, register_form.data)
+
+            redirect_to = request.POST.get("next")
+            if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
+                redirect_to = reverse("kiwipycon_account")
+
+            return set_message_cookie(
+                redirect_to, msg = u"You have been registered and logged in.")
+
+    # Get next_url
+    next_url = request.REQUEST.get("next")
+    if next_url is None:
+        next_url = request.META.get("HTTP_REFERER")
+    if next_url is None:
+        next_url = reverse("kiwipycon_account")
+    # Get just the path of the url. See django.contrib.auth.views.login for more
+    next_url = urlparse(next_url)
+    next_url = next_url[2]
+
+    try:
+        login_form_errors = login_form.errors["__all__"]
+    except KeyError:
+        login_form_errors = None
+
+    return render_to_response(template_name, RequestContext(request, {
+        "login_form" : login_form,
+        "login_form_errors" : login_form_errors,
+        "register_form" : register_form,
+        "next_url" : next_url,
+    }))
+
+def logout(request):
+    """Custom method to logout a user.
+
+    The reason to use a custom logout method is just to provide a login and a
+    logoutmethod on one place.
+    """
+    from django.contrib.auth import logout
+    logout(request)
+
+    redirect_to = '/'
+    return set_message_cookie(redirect_to, msg = u"You have been logged out.")
+
+@login_required
+def password(request, template_name="user/password.html"):
+    """Changes the password of current user.
+    """
+    if request.method == "POST":
+        form = PasswordChangeForm(request.user, request.POST)
+        if form.is_valid():
+            form.save()
+            redirect_to = reverse("kiwipycon_account")
+            return set_message_cookie(redirect_to,
+                    msg = u"Your password has been changed.")
+    else:
+        form = PasswordChangeForm(request.user)
+
+    return render_to_response(template_name, RequestContext(request, {
+        "form" : form
+    }))
+
+@login_required
+def username(request, template_name="user/username.html"):
+    """Saves the username from the data form.
+    """
+    if request.method == "POST":
+        username_form = UsernameForm(initial={"username" : request.user.username}, data=request.POST)
+        if username_form.is_valid():
+            request.user.username = username_form.cleaned_data.get("username")
+            request.user.save()
+            redirect_to = reverse("kiwipycon_account")
+            return set_message_cookie(redirect_to,
+                    msg = u"Your username has been changed.")
+    else:        
+        username_form = UsernameForm(initial={"username" : request.user.username})
+
+    return render_to_response(template_name, RequestContext(request, {
+        "form": username_form
+    }))
+
+
+def get_usernames(request):
+    """Returns in json the list of ten possible usernames
+    starting with the last pattern in the comma separated string
+    """
+
+    get_params = request.GET
+    authors_str = get_params.get('input')
+
+    if not authors_str:
+        return HttpResponse(json.dumps(''))
+
+    authors = authors_str.split(',')
+    search_author = authors[-1].strip()
+
+    users = User.objects.filter(
+        Q(username__istartswith=search_author) | Q(
+        first_name__istartswith=search_author) | Q(
+        last_name__istartswith=search_author))
+
+    results = [{'id': '',
+                'info': 'plugin_header',
+                'value': 'User Names'
+              }]
+    
+    for user in users:
+        results.append(
+            {'id': 'author_name',
+             'info': str(user.get_full_name()),
+             'value': str(user.username)
+            })
+
+    json_response = {'results': results}
+
+    return HttpResponse(json.dumps(json_response))
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/scipycon/utils.py	Tue Jul 13 17:59:47 2010 +0530
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+#python
+import urllib
+import datetime
+import re
+from random import randint
+
+#django
+from django.http import HttpResponseRedirect
+
+def kiwipycon_quote(string, encoding="utf-8"):
+    """Encodes string to encoding before quoting.
+    """
+    return urllib.quote(string.encode(encoding))
+
+# from LFS
+def set_message_cookie(url, msg):
+    """Creates response object with given url and adds message cookie with passed
+    message.
+    """
+
+    # We just keep the message two seconds.
+    max_age = 2
+    expires = datetime.datetime.strftime(
+        datetime.datetime.utcnow() +
+        datetime.timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT")
+
+    response = HttpResponseRedirect(url)
+    response.set_cookie("message", kiwipycon_quote(msg), max_age=max_age, expires=expires)
+
+    return response
+
+# from django-snippets
+def slugify(inStr):
+    removelist = ["a", "an", "as", "at", "before", "but", "by", "for","from","is", "in", "into", "like", "of", "off", "on", "onto","per","since", "than", "the", "this", "that", "to", "up", "via","with"];
+    for a in removelist:
+        aslug = re.sub(r'\b'+a+r'\b','',inStr)
+    aslug = re.sub('[^\w\s-]', '', aslug).strip().lower()
+    aslug = re.sub('\s+', '-', aslug)
+    return len(aslug) > 50 and '%s-%d' % (aslug[:43], randint(100000,999999)) or aslug
--- a/project/settings.py	Thu Apr 01 11:59:35 2010 +0530
+++ b/project/settings.py	Tue Jul 13 17:59:47 2010 +0530
@@ -73,7 +73,7 @@
         'django.core.context_processors.debug',
         'django.core.context_processors.i18n',
         'django.core.context_processors.media',
-        'project.kiwipycon.context_processors.sponsors')
+        'project.scipycon.context_processors.sponsors')
 
 DEFAULT_FROM_EMAIL = 'admin@scipy.in'
 
--- a/project/setup.py	Thu Apr 01 11:59:35 2010 +0530
+++ b/project/setup.py	Tue Jul 13 17:59:47 2010 +0530
@@ -4,7 +4,7 @@
 setup(
     name='project',
     version='1.0',
-    description="KiwiPyCon django website",
+    description="SciPy.in Conference django website",
     entry_points={
         "console_scripts": [
             'initdb = scripts.initdb:main',
--- a/project/urls.py	Thu Apr 01 11:59:35 2010 +0530
+++ b/project/urls.py	Tue Jul 13 17:59:47 2010 +0530
@@ -25,75 +25,73 @@
 )
 
 # Talks, etc.
-urlpatterns += patterns('project.kiwipycon.talk.views',
-    url(r'^talks/$',  'list_talks', name='list_talks'),
-    url(r'^talks/talk/(?P<id>\d+)/$',  'talk', name='talk_detail'),
-    url(r'^submit-talk/$',  'submit_talk', name='kiwipycon_submit_talk'),
-    url(r'^edit-talk/(?P<id>\d+)/$',  'edit_talk', name='kiwipycon_edit_talk'),
-    url(r'^talks-cfp/list-talks/(?P<id>\d+)/$',  'list_talks',
-        name='kiwipycon_list_talk'),
+urlpatterns += patterns('project.scipycon.talk.views',
+    url(r'^talks/$', 'list_talks', name='list_talks'),
+    url(r'^talks/talk/(?P<id>\d+)/$', 'talk', name='talk_detail'),
+    url(r'^submit-talk/$', 'submit_talk', name='scipycon_submit_talk'),
+    url(r'^edit-talk/(?P<id>\d+)/$', 'edit_talk', name='scipycon_edit_talk'),
+    url(r'^talks-cfp/list-talks/(?P<id>\d+)/$', 'list_talks',
+        name='scipycon_list_talk'),
     )
 
 # Registration
-urlpatterns += patterns('project.kiwipycon.registration.views',
-    url(r'^invoice/$',  'invoice', name='kiwipycon_invoice'),
-    url(r'^pdf_invoice/$',  'pdf_invoice', name='kiwipycon_pdf_invoice'),
-    url(r'^registrations/$',  'registrations', name='kiwipycon_registrations'),
-    url(r'^submit-registration/$',  'submit_registration', name='kiwipycon_submit_registration'),
-    url(r'^edit-registration/(?P<id>\d+)/$',  'edit_registration',
-        name='kiwipycon_edit_registration'),
+urlpatterns += patterns('project.scipycon.registration.views',
+    url(r'^registrations/$', 'registrations', name='scipycon_registrations'),
+    url(r'^submit-registration/$', 'submit_registration', name='scipycon_submit_registration'),
+    url(r'^edit-registration/(?P<id>\d+)/$', 'edit_registration',
+        name='scipycon_edit_registration'),
     url(r'^download_csv/', 'download_csv', name="download_csv"),
     )
 
 
 # Authentication and Profile
-urlpatterns += patterns('project.kiwipycon.user.views',
-    url(r'^login/$',  'login', name='kiwipycon_login'),
-    url(r'^logout/$',  'logout', name='kiwipycon_logout'),
-    url(r'^account/$',  'account', name='kiwipycon_account'),
-    url(r'^password/$', 'password', name='kiwipycon_password'), # change pwd
-    url(r'^username/$', 'username', name='kiwipycon_username'), # change uname
-    url(r'^edit-profile/$', 'edit_profile', name='kiwipycon_edit_profile'),
-    url(r'^get-usernames/$', 'get_usernames', name='kiwipycon_get_usernames'),
+urlpatterns += patterns('project.scipycon.user.views',
+    url(r'^login/$', 'login', name='scipycon_login'),
+    url(r'^logout/$', 'logout', name='scipycon_logout'),
+    url(r'^account/$', 'account', name='scipycon_account'),
+    url(r'^password/$', 'password', name='scipycon_password'), # change pwd
+    url(r'^username/$', 'username', name='scipycon_username'), # change uname
+    url(r'^edit-profile/$', 'edit_profile', name='scipycon_edit_profile'),
+    url(r'^get-usernames/$', 'get_usernames', name='scipycon_get_usernames'),
     )
 
 # Proceedings
-urlpatterns += patterns('project.kiwipycon.proceedings.views',
+urlpatterns += patterns('project.scipycon.proceedings.views',
     url(r'^proceedings/submit/$', 'submit',
-        name='kiwipycon_submit_proceedings'),
+        name='scipycon_submit_proceedings'),
     url(r'^proceedings/submit/(?P<id>\d+)/$', 'submit', 
-        name='kiwipycon_submit_proceedings'),
+        name='scipycon_submit_proceedings'),
     url(r'^proceedings/show_paper/(?P<id>\d+)/$', 'show_paper', 
-        name='kiwipycon_show_paper'),
+        name='scipycon_show_paper'),
     )
 
 # About pages and all other static html pages
 urlpatterns += patterns('',
     url(r'^about/accommodation/$', 
         direct_to_template, {"template": "about/accommodation.html"},
-        name='accommodation'),
+        name='scipycon_accommodation'),
     url(r'^about/food/$',
-        direct_to_template, {"template": "about/food.html"}, name='food'),
+        direct_to_template, {"template": "about/food.html"}, name='scipycon_food'),
     url(r'^about/venue/$',
-        direct_to_template, {"template": "about/venue.html"}, name='venue'),
+        direct_to_template, {"template": "about/venue.html"}, name='scipycon_venue'),
     url(r'^about/reaching/$', 
         direct_to_template, {"template": "about/reaching.html"},
-        name='reaching'),
+        name='scipycon_reaching'),
     url(r'^talks-cfp/$', 
         direct_to_template, {"template": "talk/talks-cfp.html"},
-        name='talks-cfp'),
+        name='scipycon_talks_cfp'),
     url(r'^talks-cfp/schedule/$', 
         direct_to_template, {"template": "talk/schedule.html"},
-        name='schedule'),
+        name='scipycon_schedule'),
     url(r'^talks-cfp/tutorial/$', 
         direct_to_template, {"template": "talk/tutorial-schedule.html"},
-        name='tutorial-schedule'),
+        name='scipycon_tutorial_schedule'),
     url(r'^talks-cfp/sprint/$', 
         direct_to_template, {"template": "talk/sprint-schedule.html"},
-        name='sprint-schedule'),
+        name='scipycon_sprint_schedule'),
     url(r'^talks-cfp/speakers/$', 
         direct_to_template, {"template": "talk/speakers.html"},
-        name='speakers'),
+        name='scipycon_speakers'),
     (r'^accounts/', include('registration.urls')),
     )
 
--- a/sponsor.sql	Thu Apr 01 11:59:35 2010 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-INSERT INTO "sponsor_sponsor" VALUES(1,'canonical','Canonical Limited','gold','http://www.canonical.com/','*','*','*','canonical.png',5);
-INSERT INTO "sponsor_sponsor" VALUES(2,'catalyst','Catalyst IT Liimited','gold','http://catalyst.net.nz/','*','*','*','catalyst.png',5);
-INSERT INTO "sponsor_sponsor" VALUES(3,'weta-digital','Weta Digital Limited','gold','http://www.wetafx.co.nz/','*','*','*','weta.jpg',5);
-INSERT INTO "sponsor_sponsor" VALUES(4,'psf','Python Software Foundation','gold','http://www.python.org/psf/','*','*','*','psf.png',5);
-INSERT INTO "sponsor_sponsor" VALUES(5,'unfold','Unfold Limited','gold','http://www.unfold.co.nz/','*','*','*','unfold.png',5);
-INSERT INTO "sponsor_sponsor" VALUES(6,'tait','Tait Radio Communications','gold','http://www.tait.co.nz/','*','*','*','tait.png',5);
-INSERT INTO "sponsor_sponsor" VALUES(7,'encode','Encode Limited','silver','http://encode.net.nz/','*','*','*','encode.png',2);
-INSERT INTO "sponsor_sponsor" VALUES(8,'powerhouse-ventures','powerHouse Ventures Limited','silver','http://www.powerhouse-ventures.co.nz/','*','*','*','powerhouse.png',2);
-INSERT INTO "sponsor_sponsor" VALUES(9,'pretaweb','PretaWeb','silver','http://www.pretaweb.com/','*','*','*','pretaweb.png',2);
-INSERT INTO "sponsor_sponsor" VALUES(10,'vortexdna','VortexDNA','silver','http://www.vortexdna.com/','*','*','*','vortex.png',2);
-INSERT INTO "sponsor_sponsor" VALUES(11,'apress','Apress','schwag','http://apress.com/','*','*','*','apress.png',0);
-INSERT INTO "sponsor_sponsor" VALUES(12,'oreilly','O''Reilly','schwag','http://www.oreilly.com/','*','*','*','oreilly.png',0);
-INSERT INTO "sponsor_sponsor" VALUES(13,'webstock','Webstock','schwag','http://www.webstock.org.nz/','*','*','*','webstock.png',0);
-INSERT INTO "sponsor_sponsor" VALUES(14,'packt','Packt Publishing','schwag','http://www.packtpub.com/','*','*','*','packt.png',0);