Please correct the following error{{ form.error_dict|pluralize }}:
+{% endif %}
+
+
+
+
+{% endblock %}
addfile ./docs/alternate-1.css
hunk ./docs/alternate-1.css 1
+/*
+:Authors: Ian Bicking, Michael Foord
+:Contact: fuzzyman@voidspace.org.uk
+:Date: 2005/08/26
+:Version: 0.1.0
+:Copyright: This stylesheet has been placed in the public domain.
+
+Stylesheet for Docutils.
+Based on ``blue_box.css`` by Ian Bicking
+and ``html4css1.css`` revision 1.46.
+*/
+
+@import url(html4css1.css);
+
+body {
+ font-family: Arial, sans-serif;
+}
+
+em, i {
+ /* Typically serif fonts have much nicer italics */
+ font-family: Times New Roman, Times, serif;
+}
+
+a.target {
+ color: blue;
+}
+
+a.target {
+ color: blue;
+}
+
+a.toc-backref {
+ text-decoration: none;
+ color: black;
+}
+
+a.toc-backref:hover {
+ background-color: inherit;
+}
+
+a:hover {
+ background-color: #cccccc;
+}
+
+div.attention, div.caution, div.danger, div.error, div.hint,
+div.important, div.note, div.tip, div.warning {
+ background-color: #cccccc;
+ padding: 3px;
+ width: 80%;
+}
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ text-align: center;
+ background-color: #999999;
+ display: block;
+ margin: 0;
+}
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+ color: #cc0000;
+ font-family: sans-serif;
+ text-align: center;
+ background-color: #999999;
+ display: block;
+ margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: Helvetica, Arial, sans-serif;
+ border: thin solid black;
+ /* This makes the borders rounded on Mozilla, which pleases me */
+ -moz-border-radius: 8px;
+ padding: 4px;
+}
+
+h1 {
+ background-color: #444499;
+ color: #ffffff;
+ border: medium solid black;
+}
+
+h1 a.toc-backref, h2 a.toc-backref {
+ color: #ffffff;
+}
+
+h2 {
+ background-color: #666666;
+ color: #ffffff;
+ border: medium solid black;
+}
+
+h3, h4, h5, h6 {
+ background-color: #cccccc;
+ color: #000000;
+}
+
+h3 a.toc-backref, h4 a.toc-backref, h5 a.toc-backref,
+h6 a.toc-backref {
+ color: #000000;
+}
+
+h1.title {
+ text-align: center;
+ background-color: #444499;
+ color: #eeeeee;
+ border: thick solid black;
+ -moz-border-radius: 20px;
+}
+
+table.footnote {
+ padding-left: 0.5ex;
+}
+
+table.citation {
+ padding-left: 0.5ex
+}
+
+pre.literal-block, pre.doctest-block {
+ border: thin black solid;
+ padding: 5px;
+}
+
+.image img { border-style : solid;
+ border-width : 2px;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ font-size: 100%;
+}
+
+code, tt {
+ color: #000066;
+}
addfile ./docs/i18n-remind.txt
hunk ./docs/i18n-remind.txt 1
+# how to add i18n strings to gettext style translations
+cd ~/django/ghestalt
+python /usr/lib/python2.4/site-packages/django/bin/make-messages.py -l he
+poedit
+python /usr/lib/python2.4/site-packages/django/bin/compile-messages.py -l he
addfile ./docs/i18n.txt
hunk ./docs/i18n.txt 1
+===================================
+Ghestalt internationalization logic
+===================================
+
+- site_lang / base_lang
+ The main language the site was designed for. Most content
+ should have a version in this language. The central language
+ the site falls back to when it doesn't know how to display
+ something in the requested language. It is English for Ghestalt
+ (and can safely be English for most internet sites).
+- user_lang / otro_lang
+ The language of the user. If a user is NOT multilingual, this
+ will specify his known language. And he should be able to work
+ the site in this language, possibly limited to a shard of the site's
+ content available in this language.
+- cur_lang / gui_lang
+ The site's interface language. Except for the user generated content,
+ the site should be displayed in this language (i.e. menus, buttons).
+- wiki_lang / content_lang
+ The preferred or current language of the user generated content viewed.
+ When viewing the wiki, this is the language of the current wikipage being
+ displayed. A user can keep the interface in one language while moving
+ between different translations of the content he is viewing.
+- prev_lang / other_lang
+ When a user moves between languages, especially for translation
+ purposes, this language is used in a one-language-long list of recent
+ languages to allow quick inter-language navigation.
+
+Displaying wiki pages
+---------------------
+When a wiki page in a certain language is requested and does not exist,
+the English version is served. A notice suggesting to the user to translate
+the page and the translate button appear. This notice also alerts the user to
+the fact he is not navigating the English version of the wiki, but links will
+still go to the wiki_lang version of pages. If an English version is
+unavailable too, the standard missing-page page will be served.
+
+Translation button logic
+------------------------
+The translate button automatically appears in the following cases:
+
+- The wiki page does not have an English (=base_lang) version.
+- The wiki page does not have a user_lang version.
+
+The button will allow you to edit the missing wiki page, with precedence
+taken by the user_lang missing page (as it is assumed the user is more
+proficient in this language).
+
+Changing interface language
+---------------------------
+A side pane indicated the current interface language and has buttons to change
+the interface language. The buttons include quick links to the base_lang, user_lang
+and prev_lang and a button leading to a wider language selection page.
+
+Viewing translated wiki pages
+-----------------------------
+A side pane indicated the languages for which the wiki page displayed has
+translations. Clicking on the links moves you to these pages, and to navigate
+the wiki in that language.
+
+User name and wiki links
+------------------------
+User names are shown in the English version when requested in any language other than
+their user_lang (=otro_lang). In the latter language they are shown as otro_name. The
+otro_name is part of the user profile.
+
+Wiki links to pages in languages other than the one of the wiki page formatted are suffixed
+with the page's language in parenthesis.
+
+Each user has his user_lang or otro_lang specified in his profile. The profile can be
+edited by choosing a link on the ''Account Details'' page accesible from the side pane.
+
+Motivating principles
+---------------------
+Some humanization and eye-candy has been implemented. The basic idea is to have
+a strict non-English speaker be able to navigate the site provided the community has added
+appropriate content. And contribute content as well. Language barriers often intimidate
+users and a collaborative project can use many hands and cannot afford to lose the few
+gold users (metaphorically meaning the users with the most contribution).
+
addfile ./i18n/__init__.py
addfile ./i18n/models.py
hunk ./i18n/models.py 1
+from django.db import models
+
+# Create your models here.
addfile ./i18n/utils.py
hunk ./i18n/utils.py 1
+# -*- coding: utf-8 -*-
+"""
+Support functions for i18n
+"""
+from django.conf import settings
+
+LOCALIZED_LANGAUGE_NAMES = {
+ 'en' : 'English',
+# 'he' : 'Hebrew',
+ 'po' : 'Polish',
+# 'es' : 'Espanol',
+# 'es' : 'Espaol',
+# 'es' : 'Espa\xc3\xb1ol',
+ 'es' : 'Español',
+ 'he' : 'עברית',
+
+# 'he' : 'עברית',
+# 'po' : 'Polish',
+}
+
+def i18n_site_base(request):
+ if request.LANGUAGE_CODE[:2]==settings.LANGUAGE_CODE[:2]:
+ site_base = settings.SITE_BASE
+ else:
+ site_base = settings.SITE_BASE+("/intl/%s" % (request.LANGUAGE_CODE[:2]))
+ return site_base
+
+def i18n_wiki_suffix(request):
+ if request.LANGUAGE_CODE[:2]==settings.LANGUAGE_CODE[:2]:
+ return ''
+ else:
+ return '_'+request.LANGUAGE_CODE[:2]
+
+def i18n_noprefix(path):
+ if path.startswith('/intl/'):
+ return path[8:]
+ else:
+ return path
+
+def i18n_baselang(page):
+ if len(page)<3:
+ return page
+ if page[-3]=='_':
+ if settings.LANGUAGES_DICT.has_key(page[-2:]):
+ return page[:-3]
+ return page
+
+def i18n_pagelang(page):
+ if len(page)<3:
+ return settings.LANGUAGE_CODE[:2]
+ if page[-3]=='_':
+ if settings.LANGUAGES_DICT.has_key(page[-2:]):
+ return page[-2:]
+ return settings.LANGUAGE_CODE[:2]
+
+def i18n_isbase(page):
+ if len(page)<3:
+ return False
+ if page[-3]=='_':
+ if settings.LANGUAGES_DICT.has_key(page[-2:]):
+ if page[-2:] != settings.LANGUAGE_CODE[:2]:
+ return True
+ return False
+
+def i18n_lang_suffix(page):
+ if len(page)<3:
+ return ''
+ if page[-3]=='_':
+ if settings.LANGUAGES_DICT.has_key(page[-2:]):
+ if page[-2:] != settings.LANGUAGE_CODE[:2]:
+ return page[-3:]
+ return ''
+
addfile ./i18n/views.py
hunk ./i18n/views.py 1
+from django.conf import settings
+from django.http import HttpResponse, Http404, HttpResponseRedirect
+from django.template import RequestContext, Context
+from django.shortcuts import render_to_response
+from django.utils import translation
+from django.newforms import *
+from ghestalt.i18n.utils import *
+
+class I18NForm(Form):
+ language = ChoiceField(choices=settings.LANGUAGES)
+ location = ChoiceField(choices=settings.LOCATIONS)
+ nexturl = CharField(max_length=100,widget=HiddenInput)
+ def clean(self):
+ return self.clean_data
+
+def i18n_chooselang(request):
+ if request.method == 'POST':
+ form = I18NForm(request.POST)
+ if form.is_valid():
+ try:
+ if request.session['django_language'] != settings.LANGUAGE_CODE[:2]:
+ request.session['other_lang'] = request.session['django_language']
+ except KeyError:
+ pass
+ request.session['django_language'] = form.clean_data.get('language')
+ request.session['django_location'] = form.clean_data.get('location')
+# assert False, form.clean_data
+ redirect_to = '/intl/'+str(form.clean_data.get('language'))+i18n_noprefix(str(form.clean_data.get('nexturl')))
+ return HttpResponseRedirect(redirect_to)
+ else:
+ return render_to_response('chooselang.html',{'form':form,'title':'chooselang'},
+ RequestContext(request))
+ else:
+ if request.method=='GET' and request.GET.has_key('next'):
+ redirect_to = request.GET['next']
+ else:
+ redirect_to = '/'
+ form = I18NForm({'language':request.LANGUAGE_CODE[:2],'location':request.session.get('django_location','unset'),'nexturl':redirect_to})
+ return render_to_response('chooselang.html',{'form':form,'title':'chooselang'},
+ RequestContext(request))
+
+def i18ninfo(request, language=None):
+ if language:
+ translation.activate(language)
+ else:
+ language = 'none'
+ txt = _("Hello world")
+ txt += ' '+request.LANGUAGE_CODE
+ txt += ' '+str(settings.LANGUAGES_BIDI)
+ txt += ' '+str(settings.LANGUAGES)
+ txt += ' '+language
+ return HttpResponse(txt)
+
+def redirectroot(request):
+ if request.LANGUAGE_CODE[:2] != settings.LANGUAGE_CODE[:2]:
+ if not request.path.startswith('/intl/'):
+ return HttpResponseRedirect(i18n_site_base(request)+'/')
+ else:
+ try:
+ if request.session['django_language'] != request.LANGUAGE_CODE[:2]:
+ request.session['django_language'] = request.LANGUAGE_CODE[:2]
+ except KeyError:
+ pass
+ else:
+ if request.path.startswith('/intl/'):
+ try:
+ if request.session['django_language'] != request.LANGUAGE_CODE[:2]:
+ request.session['django_language'] = request.LANGUAGE_CODE[:2]
+ # get rid of pesky /intl/xx when xx is the base language
+ except KeyError:
+ pass
+ return HttpResponseRedirect(i18n_site_base(request)+'/')
+ return render_to_response('intro.html',
+ RequestContext(request))
addfile ./locale/he/LC_MESSAGES/django.mo
binary ./locale/he/LC_MESSAGES/django.mo
oldhex
*
newhex
*de12049500000000220000001c0000002c0100002f0000003c02000000000000f80200000b0000
*00f902000010000000050300000e000000160300002a0000002503000008000000500300000700
*0000590300000e0000006103000007000000700300000a00000078030000160000008303000010
*0000009a03000008000000ab03000006000000b40300000b000000bb03000016000000c7030000
*07000000de03000008000000e603000009000000ef03000015000000f9030000080000000f0400
*000900000018040000040000002204000009000000270400000800000031040000100000003a04
*0000060000004b0400002b00000052040000070000007e0400000700000086040000040000008e
*04000006000000930400000d0000009a04000006000000a80400006c010000af0400000d000000
*1c0600000f0000002a0600001a0000003a0600004b0000005506000008000000a10600000c0000
*00aa06000014000000b70600000c000000cc0600000d000000d906000016000000e70600001300
*0000fe0600000c000000120700000a0000001f070000110000002a070000130000003c07000011
*0000005007000006000000620700000f0000006907000018000000790700000a00000092070000
*0d0000009d07000004000000ab0700000b000000b00700000a000000bc07000020000000c70700
*000c000000e807000038000000f50700000c0000002e080000080000003b080000080000004408
*00000c0000004d0800001c0000005a0800000c0000007708000001000000080000001f00000000
*0000000d0000001b0000000000000000000000150000000c000000170000000f0000001d000000
*00000000140000000e00000000000000060000001e000000200000000900000000000000000000
*000300000022000000000000001300000000000000070000000000000002000000000000001000
*00001800000016000000000000000a000000040000000b0000001a000000110000002100000019
*0000001c000000000000001200000005000000002064697363757373696f6e004163636f756e74
*20757365726e616d65004269626c696f6772617068793a200043616e6e6f74207061727365206c
*6f636174696f6e2e20466f726d6174206973206c61742c6c6f6e672e00436f6e74656e74730044
*69736375737300452d6d61696c206164647265737300456e676c697368004669727374206e616d
*65004669727374206e616d6520696e206c616e67756167650047656e6572616c20717565737469
*6f6e004768657374616c74004865627265770048656c6c6f20776f726c6400496d70726f76656d
*656e742073756767657374696f6e00496e7175697279004c616e6775616765004c617374206e61
*6d65004c617374206e616d6520696e206c616e6775616765004c6f636174696f6e004d61696e20
*70616765004e616d650050616765206e616d650050617373776f72640050617373776f72642028
*616761696e2900506f6c697368005265706c616365206361726574206d61726b6564206c696e65
*732077697468207472616e736c6174696f6e005370616e697368005375626a6563740054657874
*00557365723a200057656c636f6d6520746f2025730057696b693a200050726f6a6563742d4964
*2d56657273696f6e3a204768657374616c740a5265706f72742d4d736769642d427567732d546f
*3a200a504f542d4372656174696f6e2d446174653a20323030372d30312d32392030313a33352b
*303230300a504f2d5265766973696f6e2d446174653a20323030372d30312d32392030313a3339
*2b303230300a4c6173742d5472616e736c61746f723a2044616e204765747a203c6765747a6461
*6e407961686f6f2e636f6d3e0a4c616e67756167652d5465616d3a2044616e204765747a203c67
*65747a64616e407961686f6f2e636f6d3e0a4d494d452d56657273696f6e3a20312e300a436f6e
*74656e742d547970653a20746578742f706c61696e3b20636861727365743d7574662d380a436f
*6e74656e742d5472616e736665722d456e636f64696e673a20386269740a582d506f656469742d
*4c616e67756167653a204865627265770a582d506f656469742d436f756e7472793a2049535241
*454c0a0020d7aad792d795d791d795d7aa00d7a9d79d20d79ed7a9d7aad79ed7a900d791d799d7
*91d79cd799d790d795d792d7a8d7a4d799d7943a2000d79cd79020d79ed7a6d79cd799d79720d7
*9cd794d791d799d79f20d7a4d795d7a8d79ed79820d79ed799d7a7d795d79d2e20d7a0d7a1d794
*20d790d795d7a8d79a2c20d7a8d795d797d79100d7aad795d79bd79f00d7aad792d795d791d795
*d7aa00d79bd7aad795d791d7aa20d793d795d79022d79c00d790d7a0d792d79cd799d7aa00d7a9
*d79d20d7a4d7a8d798d79900d7a9d79d20d7a4d7a8d798d79920d791d7a9d7a4d79400d7a9d790
*d79cd79420d79bd79cd79cd799d7aa00d792d794d7a9d798d79cd79800d7a2d791d7a8d799d7aa
*00d7a9d79cd795d79d20d7a2d795d79cd79d00d794d7a6d7a2d7aa20d7a9d799d7a4d795d7a800
*d7a1d795d79220d794d7a4d7a0d799d79400d7a9d7a4d79400d7a9d79d20d79ed7a9d7a4d797d7
*9400d7a9d79d20d79ed7a9d7a4d797d79420d791d7a9d7a4d79400d79ed799d7a7d795d79d00d7
*93d7a320d7a8d790d7a9d79900d7a9d79d00d7a9d79d20d794d793d7a300d7a1d799d7a1d79ed7
*9400d7a1d799d7a1d79ed7942028d7a9d795d79120d79cd790d799d79ed795d7aa2900d7a4d795
*d79cd7a0d799d7aa00d794d797d79cd7a320d7a9d795d7a8d795d7aa20d794d79ed7aad797d799
*d79cd795d7aa20d7912d5e20d791d7aad7a8d792d795d79ed79f00d7a1d7a4d7a8d793d799d7aa
*00d7a0d795d7a9d79000d798d7a7d7a1d79800d79ed7a9d7aad79ed7a93a2000d791d7a8d795d7
*9bd799d79d20d794d791d790d799d79d20d79c257300d795d795d799d7a7d7993a2000
addfile ./locale/he/LC_MESSAGES/django.po
hunk ./locale/he/LC_MESSAGES/django.po 1
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Ghestalt\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-01-29 01:35+0200\n"
+"PO-Revision-Date: 2007-01-29 01:39+0200\n"
+"Last-Translator: Dan Getz \n"
+"Language-Team: Dan Getz \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Hebrew\n"
+"X-Poedit-Country: ISRAEL\n"
+
+#: settings.py:10
+msgid "Ghestalt"
+msgstr "גהשטלט"
+
+#: settings.py:105
+msgid "English"
+msgstr "אנגלית"
+
+#: settings.py:106
+msgid "Hebrew"
+msgstr "עברית"
+
+#: settings.py:107
+msgid "Polish"
+msgstr "פולנית"
+
+#: settings.py:108
+msgid "Spanish"
+msgstr "ספרדית"
+
+#: i18n/views.py:47
+msgid "Hello world"
+msgstr "שלום עולם"
+
+#: app/views.py:14
+msgid "Wiki: "
+msgstr "וויקי: "
+
+#: app/views.py:14
+msgid "Bibliography: "
+msgstr "ביבליאוגרפיה: "
+
+#: app/views.py:14
+msgid "User: "
+msgstr "משתמש: "
+
+#: app/views.py:22
+msgid " discussion"
+msgstr " תגובות"
+
+#: app/views.py:88
+msgid "Page name"
+msgstr "שם הדף"
+
+#: app/views.py:89
+#: app/models.py:26
+#: app/accounts.py:29
+#: app/accounts.py:126
+msgid "Language"
+msgstr "שפה"
+
+#: app/views.py:110
+msgid "Text"
+msgstr "טקסט"
+
+#: app/views.py:142
+msgid "Replace caret marked lines with translation"
+msgstr "החלף שורות המתחילות ב-^ בתרגומן"
+
+#: app/contact.py:11
+msgid "General question"
+msgstr "שאלה כללית"
+
+#: app/contact.py:12
+msgid "Improvement suggestion"
+msgstr "הצעת שיפור"
+
+#: app/contact.py:16
+msgid "Name"
+msgstr "שם"
+
+#: app/contact.py:17
+#: app/accounts.py:22
+msgid "E-mail address"
+msgstr "כתובת דוא\"ל"
+
+#: app/contact.py:18
+msgid "Subject"
+msgstr "נושא"
+
+#: app/contact.py:19
+msgid "Inquiry"
+msgstr "סוג הפניה"
+
+#: app/contact.py:20
+msgid "Contents"
+msgstr "תוכן"
+
+#: app/accounts.py:23
+msgid "Password"
+msgstr "סיסמה"
+
+#: app/accounts.py:24
+msgid "Password (again)"
+msgstr "סיסמה (שוב לאימות)"
+
+#: app/accounts.py:25
+#: app/accounts.py:123
+msgid "First name"
+msgstr "שם פרטי"
+
+#: app/accounts.py:26
+#: app/accounts.py:124
+msgid "Last name"
+msgstr "שם משפחה"
+
+#: app/accounts.py:27
+msgid "Account username"
+msgstr "שם משתמש"
+
+#: app/accounts.py:28
+#: app/accounts.py:125
+msgid "Location"
+msgstr "מיקום"
+
+#: app/accounts.py:30
+#: app/accounts.py:127
+msgid "First name in language"
+msgstr "שם פרטי בשפה"
+
+#: app/accounts.py:31
+#: app/accounts.py:128
+msgid "Last name in language"
+msgstr "שם משפחה בשפה"
+
+#: app/accounts.py:42
+#: app/accounts.py:45
+#: app/accounts.py:52
+#: app/accounts.py:60
+#: app/accounts.py:135
+#: app/accounts.py:138
+#: app/accounts.py:145
+#: app/accounts.py:153
+msgid "Cannot parse location. Format is lat,long."
+msgstr "לא מצליח להבין פורמט מיקום. נסה אורך, רוחב"
+
+#: app/accounts.py:96
+#, python-format
+msgid "Welcome to %s"
+msgstr "ברוכים הבאים ל%s"
+
+#: app/templatetags/ghmarkup.py:301
+msgid "Main page"
+msgstr "דף ראשי"
+
+#: app/templatetags/ghmarkup.py:303
+msgid "Discuss"
+msgstr "תגובות"
+
+#~ msgid "Autoswitch language"
+#~ msgstr "החלפת שפה אוטומטית"
+#~ msgid ""
+#~ "Check box if you wish system would switch to your language during login"
+#~ msgstr "סמן את המשבצת אם ברצונך שהמערכת תחליף לשפת המשתמש מיד עם הכניסה"
+#~ msgid "Ghilbert"
+#~ msgstr "גהילברט"
+
addfile ./middleware/__init__.py
addfile ./middleware/localeurl.py
hunk ./middleware/localeurl.py 1
+from django.utils.cache import patch_vary_headers
+from django.utils import translation
+
+class LocaleURLMiddleware:
+ def get_language_from_request (self,request):
+ from django.conf import settings
+ import re
+ supported = dict(settings.LANGUAGES)
+ lang = settings.LANGUAGE_CODE[:2]
+ check = re.match(r".*/intl/(\w\w)/.*", request.path)
+ changed = False
+ if check is not None:
+ t = check.group(1)
+ if t in supported:
+ lang = t
+ changed = True
+ if not changed:
+ if hasattr(request, 'session'):
+ lang = request.session.get('django_language', None)
+ if lang in supported and lang is not None:
+ return lang
+ else:
+ lang = request.COOKIES.get('django_language', None)
+ if lang in supported and lang is not None:
+ return lang
+ return lang
+ def process_request(self, request):
+ from django.conf import settings
+ language = self.get_language_from_request(request)
+ if language is None:
+ language = settings.LANGUAGE_CODE[:2]
+ translation.activate(language)
+# assert False, translation.get_language()+translation.gettext('Hello world')
+ request.LANGUAGE_CODE = str(translation.get_language())
+ def process_response(self, request, response):
+ from django.conf import settings
+ patch_vary_headers(response, ('Accept-Language',))
+ language = self.get_language_from_request(request)
+ if language is None:
+ language = settings.LANGUAGE_CODE[:2]
+# if language == settings.LANGUAGE_CODE[:2]:
+# response.content = response.content.replace('/intl/xx','')
+# else:
+# response.content = response.content.replace('/intl/xx','/intl/'+language)
+ translation.deactivate()
+ return response
+
+def get_absolute_path_without_lang(request):
+ for lang in settings.LANGUAGES:
+ if '/' + str(lang[0]) + '/' in request.path:
+ return request.path.replace('/' + str(lang[0]) + '/', '/')
+ return request.path
addfile ./patches/django-ghestalt.diff
hunk ./patches/django-ghestalt.diff 1
+diff -Nuar django-with-fixtures/django/core/management.py django-ghestalt/django/core/management.py
+--- django-with-fixtures/django/core/management.py 2007-01-29 15:08:45.000000000 -0800
++++ django-ghestalt/django/core/management.py 2007-02-04 04:49:14.000000000 -0800
+@@ -1368,8 +1368,9 @@
+ sys.stderr.write(
+ style.ERROR("Problem installing %s fixture '%s' from '%s': %s\n" %
+ (format, fixture_name, fixture_dir, str(e))))
++ raise
+ fixture.close()
+- except:
++ except IOError:
+ if verbosity > 1:
+ print "No %s fixture '%s' in '%s'" % (format, fixture_name, fixture_dir)
+ if count[0] == 0:
+diff -Nuar django-with-fixtures/django/core/validators.py django-ghestalt/django/core/validators.py
+--- django-with-fixtures/django/core/validators.py 2006-11-06 20:29:07.000000000 -0800
++++ django-ghestalt/django/core/validators.py 2007-02-04 04:49:14.000000000 -0800
+@@ -143,6 +143,7 @@
+ raise ValidationError, gettext('Invalid date: %s.' % e)
+
+ def isValidANSIDate(field_data, all_data):
++ if not field_data: return None
+ if not ansi_date_re.search(field_data):
+ raise ValidationError, gettext('Enter a valid date in YYYY-MM-DD format.')
+ _isValidDate(field_data)
+diff -Nuar django-with-fixtures/django/db/backends/util.py django-ghestalt/django/db/backends/util.py
+--- django-with-fixtures/django/db/backends/util.py 2006-12-29 22:25:49.000000000 -0800
++++ django-ghestalt/django/db/backends/util.py 2007-01-29 15:15:45.000000000 -0800
+@@ -14,12 +14,13 @@
+ stop = time()
+ # If params was a list, convert it to a tuple, because string
+ # formatting with '%' only works with tuples or dicts.
+- if not isinstance(params, (tuple, dict)):
+- params = tuple(params)
+- self.db.queries.append({
+- 'sql': sql % params,
+- 'time': "%.3f" % (stop - start),
+- })
++#### this debugging code seems to break something with unicode strings
++# if not isinstance(params, (tuple, dict)):
++# params = tuple(params)
++# self.db.queries.append({
++# 'sql': sql % params,
++# 'time': "%.3f" % (stop - start),
++# })
+
+ def executemany(self, sql, param_list):
+ start = time()
+diff -Nuar django-with-fixtures/django/db/models/fields/__init__.py django-ghestalt/django/db/models/fields/__init__.py
+--- django-with-fixtures/django/db/models/fields/__init__.py 2007-01-28 14:36:02.000000000 -0800
++++ django-ghestalt/django/db/models/fields/__init__.py 2007-02-04 04:49:14.000000000 -0800
+@@ -437,6 +437,8 @@
+ Field.__init__(self, verbose_name, name, **kwargs)
+
+ def to_python(self, value):
++ if value is None:
++ return None
+ if isinstance(value, datetime.datetime):
+ return value.date()
+ if isinstance(value, datetime.date):
+diff -Nuar django-with-fixtures/django/utils/simplejson/decoder.py django-ghestalt/django/utils/simplejson/decoder.py
+--- django-with-fixtures/django/utils/simplejson/decoder.py 2006-12-29 22:25:49.000000000 -0800
++++ django-ghestalt/django/utils/simplejson/decoder.py 2007-02-04 04:49:14.000000000 -0800
+@@ -65,6 +65,13 @@
+
+ DEFAULT_ENCODING = "utf-8"
+
++def smart_unicode(s):
++ if not isinstance(s, basestring):
++ s = unicode(str(s))
++ elif not isinstance(s, unicode):
++ s = unicode(s, settings.DEFAULT_ENCODING)
++ return s
++
+ def scanstring(s, end, encoding=None, _b=BACKSLASH, _m=STRINGCHUNK.match):
+ if encoding is None:
+ encoding = DEFAULT_ENCODING
+@@ -106,7 +113,7 @@
+ raise ValueError(errmsg("Invalid \\uXXXX escape", s, end))
+ end += 5
+ _append(m)
+- return u''.join(chunks), end
++ return u''.join(map(lambda x: smart_unicode(x),chunks)), end
+
+ def JSONString(match, context):
+ encoding = getattr(context, 'encoding', None)
addfile ./patches/fixtures.diff
hunk ./patches/fixtures.diff 1
+Index: django/test/testcases.py
+===================================================================
+--- django/test/testcases.py (revision 4223)
++++ django/test/testcases.py (working copy)
+@@ -1,5 +1,7 @@
+ import re, doctest, unittest
+ from django.db import transaction
++from django.core import management
++from django.db.models import get_apps
+
+ normalize_long_ints = lambda s: re.sub(r'(?0:
++ # sequence name in this case will be
__seq
++ sql.append("%s %s %s %s %s %s;" % \
++ (style.SQL_KEYWORD('ALTER'),
++ style.SQL_KEYWORD('SEQUENCE'),
++ style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)),
++ style.SQL_KEYWORD('RESTART'),
++ style.SQL_KEYWORD('WITH'),
++ style.SQL_FIELD('1')
++ )
++ )
++ else:
++ # sequence name in this case will be
_id_seq
++ sql.append("%s %s %s %s %s %s;" % \
++ (style.SQL_KEYWORD('ALTER'),
++ style.SQL_KEYWORD('SEQUENCE'),
++ style.SQL_FIELD('%s_id_seq' % table_name),
++ style.SQL_KEYWORD('RESTART'),
++ style.SQL_KEYWORD('WITH'),
++ style.SQL_FIELD('1')
++ )
++ )
++ return sql
++ else:
++ return []
++
+ # Register these custom typecasts, because Django expects dates/times to be
+ # in Python's native (standard-library) datetime/time format, whereas psycopg
+ # use mx.DateTime by default.
+Index: django/db/backends/sqlite3/base.py
+===================================================================
+--- django/db/backends/sqlite3/base.py (revision 4223)
++++ django/db/backends/sqlite3/base.py (working copy)
+@@ -148,6 +148,24 @@
+ def get_pk_default_value():
+ return "NULL"
+
++def get_sql_flush(style, tables, sequences):
++ """Return a list of SQL statements required to remove all data from
++ all tables in the database (without actually removing the tables
++ themselves) and put the database in an empty 'initial' state
++
++ """
++ # NB: The generated SQL below is specific to SQLite
++ # Note: The DELETE FROM... SQL generated below works for SQLite databases
++ # because constraints don't exist
++ sql = ['%s %s %s;' % \
++ (style.SQL_KEYWORD('DELETE'),
++ style.SQL_KEYWORD('FROM'),
++ style.SQL_FIELD(quote_name(table))
++ ) for table in tables]
++ # Note: No requirement for reset of auto-incremented indices (cf. other
++ # get_sql_flush() implementations). Just return SQL at this point
++ return sql
++
+ def _sqlite_date_trunc(lookup_type, dt):
+ try:
+ dt = util.typecast_timestamp(dt)
+Index: django/db/backends/mysql/base.py
+===================================================================
+--- django/db/backends/mysql/base.py (revision 4223)
++++ django/db/backends/mysql/base.py (working copy)
+@@ -181,6 +181,33 @@
+ def get_pk_default_value():
+ return "DEFAULT"
+
++def get_sql_flush(style, tables, sequences):
++ """Return a list of SQL statements required to remove all data from
++ all tables in the database (without actually removing the tables
++ themselves) and put the database in an empty 'initial' state
++
++ """
++ # NB: The generated SQL below is specific to MySQL
++ # 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
++ # to clear all tables of all data
++ if tables:
++ sql = ['%s %s;' % \
++ (style.SQL_KEYWORD('TRUNCATE'),
++ style.SQL_FIELD(quote_name(table))
++ ) for table in tables]
++ # 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements
++ # to reset sequence indices
++ sql.extend(["%s %s %s %s %s;" % \
++ (style.SQL_KEYWORD('ALTER'),
++ style.SQL_KEYWORD('TABLE'),
++ style.SQL_TABLE(quote_name(sequence['table'])),
++ style.SQL_KEYWORD('AUTO_INCREMENT'),
++ style.SQL_FIELD('= 1'),
++ ) for sequence in sequences])
++ return sql
++ else:
++ return []
++
+ OPERATOR_MAPPING = {
+ 'exact': '= %s',
+ 'iexact': 'LIKE %s',
+Index: django/db/backends/oracle/base.py
+===================================================================
+--- django/db/backends/oracle/base.py (revision 4223)
++++ django/db/backends/oracle/base.py (working copy)
+@@ -117,6 +117,20 @@
+ def get_pk_default_value():
+ return "DEFAULT"
+
++def get_sql_flush(style, tables, sequences):
++ """Return a list of SQL statements required to remove all data from
++ all tables in the database (without actually removing the tables
++ themselves) and put the database in an empty 'initial' state
++ """
++ # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
++ # TODO - SQL not actually tested against Oracle yet!
++ # TODO - autoincrement indices reset required? See other get_sql_flush() implementations
++ sql = ['%s %s;' % \
++ (style.SQL_KEYWORD('TRUNCATE'),
++ style.SQL_FIELD(quote_name(table))
++ ) for table in tables]
++
++
+ OPERATOR_MAPPING = {
+ 'exact': '= %s',
+ 'iexact': 'LIKE %s',
+Index: django/db/backends/postgresql_psycopg2/base.py
+===================================================================
+--- django/db/backends/postgresql_psycopg2/base.py (revision 4223)
++++ django/db/backends/postgresql_psycopg2/base.py (working copy)
+@@ -105,6 +105,50 @@
+ def get_pk_default_value():
+ return "DEFAULT"
+
++def get_sql_flush(style, tables, sequences):
++ """Return a list of SQL statements required to remove all data from
++ all tables in the database (without actually removing the tables
++ themselves) and put the database in an empty 'initial' state
++ """
++ # Postgres can do 'TRUNCATE x, y, z...;'. In fact, it *has to* in order to be able to
++ # truncate tables referenced by a foreign key in any other table. The result is a
++ # single SQL TRUNCATE statement
++ if tables:
++ sql = ['%s %s;' % \
++ (style.SQL_KEYWORD('TRUNCATE'),
++ style.SQL_FIELD(', '.join(quote_name(table) for table in tables))
++ )]
++ # 'ALTER SEQUENCE sequence_name RESTART WITH 1;'... style SQL statements
++ # to reset sequence indices
++ for sequence in sequences:
++ table_name = sequence['table']
++ column_name = sequence['column']
++ if column_name and len(column_name) > 0:
++ # sequence name in this case will be
__seq
++ sql.append("%s %s %s %s %s %s;" % \
++ (style.SQL_KEYWORD('ALTER'),
++ style.SQL_KEYWORD('SEQUENCE'),
++ style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)),
++ style.SQL_KEYWORD('RESTART'),
++ style.SQL_KEYWORD('WITH'),
++ style.SQL_FIELD('1')
++ )
++ )
++ else:
++ # sequence name in this case will be
_id_seq
++ sql.append("%s %s %s %s %s %s;" % \
++ (style.SQL_KEYWORD('ALTER'),
++ style.SQL_KEYWORD('SEQUENCE'),
++ style.SQL_FIELD('%s_id_seq' % table_name),
++ style.SQL_KEYWORD('RESTART'),
++ style.SQL_KEYWORD('WITH'),
++ style.SQL_FIELD('1')
++ )
++ )
++ return sql
++ else:
++ return []
++
+ OPERATOR_MAPPING = {
+ 'exact': '= %s',
+ 'iexact': 'ILIKE %s',
+Index: django/db/backends/dummy/base.py
+===================================================================
+--- django/db/backends/dummy/base.py (revision 4223)
++++ django/db/backends/dummy/base.py (working copy)
+@@ -38,4 +38,6 @@
+ get_random_function_sql = complain
+ get_fulltext_search_sql = complain
+ get_drop_foreignkey_sql = complain
++get_sql_flush = complain
++
+ OPERATOR_MAPPING = {}
+Index: django/core/serializers/base.py
+===================================================================
+--- django/core/serializers/base.py (revision 4223)
++++ django/core/serializers/base.py (working copy)
+@@ -141,7 +141,7 @@
+
+ class DeserializedObject(object):
+ """
+- A deserialzed model.
++ A deserialized model.
+
+ Basically a container for holding the pre-saved deserialized data along
+ with the many-to-many data saved with the object.
+Index: django/core/management.py
+===================================================================
+--- django/core/management.py (revision 4223)
++++ django/core/management.py (working copy)
+@@ -68,6 +68,25 @@
+ cursor = connection.cursor()
+ return get_introspection_module().get_table_list(cursor)
+
++def _get_sequence_list():
++ "Returns a list of information about all DB sequences for all models in all apps"
++ from django.db import models
++
++ apps = models.get_apps()
++ sequence_list = []
++
++ for app in apps:
++ for model in models.get_models(app):
++ for f in model._meta.fields:
++ if isinstance(f, models.AutoField):
++ sequence_list.append({'table':model._meta.db_table,'column':f.column,})
++ break # Only one AutoField is allowed per model, so don't bother continuing.
++
++ for f in model._meta.many_to_many:
++ sequence_list.append({'table':f.m2m_db_table(),'column':None,})
++
++ return sequence_list
++
+ # If the foreign key points to an AutoField, a PositiveIntegerField or a
+ # PositiveSmallIntegerField, the foreign key should be an IntegerField, not the
+ # referred field type. Otherwise, the foreign key should be the same type of
+@@ -330,7 +349,15 @@
+ get_sql_reset.help_doc = "Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s)."
+ get_sql_reset.args = APP_ARGS
+
+-def get_sql_initial_data_for_model(model):
++def get_sql_flush():
++ "Returns a list of the SQL statements used to flush the database"
++ from django.db import backend
++ statements = backend.get_sql_flush(style, _get_table_list(), _get_sequence_list())
++ return statements
++get_sql_flush.help_doc = "Returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed."
++get_sql_flush.args = ''
++
++def get_custom_sql_for_model(model):
+ from django.db import models
+ from django.conf import settings
+
+@@ -357,8 +384,8 @@
+
+ return output
+
+-def get_sql_initial_data(app):
+- "Returns a list of the initial INSERT SQL statements for the given app."
++def get_custom_sql(app):
++ "Returns a list of the custom table modifying SQL statements for the given app."
+ from django.db.models import get_models
+ output = []
+
+@@ -366,11 +393,11 @@
+ app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
+
+ for model in app_models:
+- output.extend(get_sql_initial_data_for_model(model))
++ output.extend(get_custom_sql_for_model(model))
+
+ return output
+-get_sql_initial_data.help_doc = "Prints the initial INSERT SQL statements for the given app name(s)."
+-get_sql_initial_data.args = APP_ARGS
++get_custom_sql.help_doc = "Prints the custom table modifying SQL statements for the given app name(s)."
++get_custom_sql.args = APP_ARGS
+
+ def get_sql_sequence_reset(app):
+ "Returns a list of the SQL statements to reset PostgreSQL sequences for the given app."
+@@ -428,7 +455,7 @@
+
+ def get_sql_all(app):
+ "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
+- return get_sql_create(app) + get_sql_initial_data(app) + get_sql_indexes(app)
++ return get_sql_create(app) + get_custom_sql(app) + get_sql_indexes(app)
+ get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
+ get_sql_all.args = APP_ARGS
+
+@@ -511,10 +538,10 @@
+ # just created)
+ for model in models.get_models(app):
+ if model in created_models:
+- initial_sql = get_sql_initial_data_for_model(model)
++ initial_sql = get_custom_sql_for_model(model)
+ if initial_sql:
+ if verbosity >= 1:
+- print "Installing initial data for %s.%s model" % (app_name, model._meta.object_name)
++ print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name)
+ try:
+ for sql in initial_sql:
+ cursor.execute(sql)
+@@ -670,6 +697,70 @@
+ reset.help_doc = "Executes ``sqlreset`` for the given app(s) in the current database."
+ reset.args = APP_ARGS
+
++def flush(verbosity=1, interactive=True):
++ "Returns all tables in the database to the same state they were in immediately after syncdb."
++ from django.db import connection, transaction, models
++ from django.conf import settings
++ from django.dispatch import dispatcher
++
++ disable_termcolors()
++
++ # First, try validating the models.
++ _check_for_validation_errors()
++
++ # Import the 'management' module within each installed app, to register
++ # dispatcher events.
++ for app_name in settings.INSTALLED_APPS:
++ try:
++ __import__(app_name + '.management', {}, {}, [''])
++ except ImportError:
++ pass
++
++ sql_list = get_sql_flush()
++
++ if interactive:
++ confirm = raw_input("""
++You have requested a flush of the database.
++This will IRREVERSIBLY DESTROY all data currently in the database,
++and return each table to the state it was in after syncdb.
++Are you sure you want to do this?
++
++Type 'yes' to continue, or 'no' to cancel: """)
++ else:
++ confirm = 'yes'
++
++ if confirm == 'yes':
++ try:
++ cursor = connection.cursor()
++ for sql in sql_list:
++ cursor.execute(sql)
++ except Exception, e:
++ sys.stderr.write(style.ERROR("""Error: Database %s couldn't be flushed. Possible reasons:
++ * The database isn't running or isn't configured correctly.
++ * At least one of the expected database tables doesn't exist.
++ * The SQL was invalid.
++Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run.
++The full error: """ % settings.DATABASE_NAME + style.ERROR_OUTPUT(str(e)) + '\n'))
++ transaction.rollback_unless_managed()
++ sys.exit(1)
++ transaction.commit_unless_managed()
++
++ # Emit the post-syncdb signal for every application.
++ # This simulates the effect of installing every application clean.
++ for app in models.get_apps():
++ app_name = app.__name__.split('.')[-2]
++ model_list = models.get_models(app)
++ if verbosity >= 2:
++ print "Running post-sync handlers for application", app_name
++ dispatcher.send(signal=models.signals.post_syncdb, sender=app,
++ app=app, created_models=model_list,
++ verbosity=verbosity, interactive=interactive)
++
++ else:
++ print "Flush cancelled."
++flush.help_doc = "Executes ``sqlflush`` on the current database."
++flush.args = ''
++
+ def _start_helper(app_or_project, name, directory, other_name=''):
+ other = {'project': 'app', 'app': 'project'}[app_or_project]
+ if not _is_valid_dir_name(name):
+@@ -751,7 +842,7 @@
+ yield "# * Make sure each model has one field with primary_key=True"
+ yield "# Feel free to rename the models, but don't rename db_table values or field names."
+ yield "#"
+- yield "# Also note: You'll have to insert the output of 'django-admin.py sqlinitialdata [appname]'"
++ yield "# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'"
+ yield "# into your database."
+ yield ''
+ yield 'from django.db import models'
+@@ -1239,6 +1330,86 @@
+ test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
+ test.args = '[--verbosity] ' + APP_ARGS
+
++def install_fixtures(fixture_labels, format='json', verbosity=1):
++ "Installs the fixture(s) with the provided name(s)"
++ from django.db.models import get_apps
++ from django.core import serializers
++ from django.db import transaction
++ from django.conf import settings
++ import sys
++
++ # Keep a count of the installed objects and fixtures
++ count = [0,0]
++
++ serializer = serializers.get_serializer(format)
++
++ if verbosity > 1:
++ print "Looking for %s fixtures..." % format
++
++ app_fixtures = [os.path.join(os.path.dirname(app.__file__),'fixtures') for app in get_apps()]
++ for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS):
++ if verbosity > 1:
++ print "Checking '%s' for %s fixtures..." % (fixture_dir, format)
++ for fixture_name in fixture_labels:
++ try:
++ if verbosity > 1:
++ print "Trying %s fixture '%s' from '%s'." % (format, fixture_name, fixture_dir)
++ fixture = open(os.path.join(fixture_dir,
++ '.'.join([fixture_name, format])),
++ 'r')
++ count[1] += 1
++ if verbosity > 0:
++ print "Installing %s fixture '%s' from '%s'." % (format, fixture_name, fixture_dir)
++ try:
++ for obj in serializers.deserialize(format, fixture):
++ count[0] += 1
++ obj.save()
++ except Exception, e:
++ sys.stderr.write(
++ style.ERROR("Problem installing %s fixture '%s' from '%s': %s\n" %
++ (format, fixture_name, fixture_dir, str(e))))
++ fixture.close()
++ except:
++ if verbosity > 1:
++ print "No %s fixture '%s' in '%s'" % (format, fixture_name, fixture_dir)
++ if count[0] == 0:
++ if verbosity > 0:
++ print "No fixtures found"
++ else:
++ if verbosity > 0:
++ print "Installed %d objects from %d fixtures" % tuple(count)
++ transaction.commit_unless_managed()
++install_fixtures.help_doc = 'Installs the named fixture(s) in the database'
++install_fixtures.args = "[--format] [--verbosity] fixture_name, fixture_name, ..."
++
++def dumpdb(app_labels, format='json'):
++ "Output the current contents of the database as a fixture of the given format"
++ from django.db.models import get_app, get_apps, get_models
++ from django.core import serializers
++
++ if len(app_labels) == 0:
++ app_list = get_apps()
++ else:
++ app_list = [get_app(app_label) for app_label in app_labels]
++
++ # Check that the serialization format exists; this is a shortcut to
++ # avoid collating all the objects and _then_ failing.
++ try:
++ serializers.get_serializer(format)
++ except KeyError:
++ sys.stderr.write(style.ERROR("Unknown serialization format: %s\n" % format))
++
++ objects = []
++ for app in app_list:
++ for model in get_models(app):
++ objects.extend(model.objects.all())
++ try:
++ print serializers.serialize(format, objects)
++ except Exception, e:
++ sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e))
++dumpdb.help_doc = 'Output the contents of the database as a fixture of the given format'
++dumpdb.args = '[--format]' + APP_ARGS
++
+ # Utilities for command-line script
+
+ DEFAULT_ACTION_MAPPING = {
+@@ -1246,8 +1417,11 @@
+ 'createcachetable' : createcachetable,
+ 'dbshell': dbshell,
+ 'diffsettings': diffsettings,
++ 'dumpdb': dumpdb,
++ 'flush': flush,
+ 'inspectdb': inspectdb,
+ 'install': install,
++ 'installfixture': install_fixtures,
+ 'reset': reset,
+ 'runfcgi': runfcgi,
+ 'runserver': runserver,
+@@ -1255,8 +1429,9 @@
+ 'sql': get_sql_create,
+ 'sqlall': get_sql_all,
+ 'sqlclear': get_sql_delete,
++ 'sqlcustom': get_custom_sql,
++ 'sqlflush': get_sql_flush,
+ 'sqlindexes': get_sql_indexes,
+- 'sqlinitialdata': get_sql_initial_data,
+ 'sqlreset': get_sql_reset,
+ 'sqlsequencereset': get_sql_sequence_reset,
+ 'startapp': startapp,
+@@ -1318,6 +1493,8 @@
+ help='Tells Django to NOT prompt the user for input of any kind.')
+ parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
+ help='Tells Django to NOT use the auto-reloader when running the development server.')
++ parser.add_option('--format', default='json', dest='format',
++ help='Specifies the serialization format for fixtures')
+ parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
+ type='choice', choices=['0', '1', '2'],
+ help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+@@ -1351,7 +1528,7 @@
+ action_mapping[action](options.plain is True)
+ elif action in ('validate', 'diffsettings', 'dbshell'):
+ action_mapping[action]()
+- elif action == 'syncdb':
++ elif action in ('flush', 'syncdb'):
+ action_mapping[action](int(options.verbosity), options.interactive)
+ elif action == 'inspectdb':
+ try:
+@@ -1370,6 +1547,16 @@
+ action_mapping[action](args[1:], int(options.verbosity))
+ except IndexError:
+ parser.print_usage_and_exit()
++ elif action == 'installfixture':
++ try:
++ action_mapping[action](args[1:], options.format, int(options.verbosity))
++ except IndexError:
++ parser.print_usage_and_exit()
++ elif action == 'dumpdb':
++ try:
++ action_mapping[action](args[1:], options.format)
++ except IndexError:
++ parser.print_usage_and_exit()
+ elif action in ('startapp', 'startproject'):
+ try:
+ name = args[1]
+@@ -1388,6 +1575,8 @@
+ action_mapping[action](addr, port, options.use_reloader, options.admin_media_path)
+ elif action == 'runfcgi':
+ action_mapping[action](args[1:])
++ elif action == 'sqlflush':
++ print '\n'.join(action_mapping[action]())
+ else:
+ from django.db import models
+ validate(silent_success=True)
+
+Property changes on: tests/modeltests/fixtures
+___________________________________________________________________
+Name: svn:ignore
+ + *.pyc
+
+
+Index: tests/modeltests/fixtures/__init__.py
+===================================================================
+
+Property changes on: tests/modeltests/fixtures/fixtures
+___________________________________________________________________
+Name: svn:ignore
+ + *.pyc
+
+
+Index: tests/modeltests/fixtures/fixtures/fixture1.json
+===================================================================
+--- tests/modeltests/fixtures/fixtures/fixture1.json (revision 0)
++++ tests/modeltests/fixtures/fixtures/fixture1.json (revision 0)
+@@ -0,0 +1,18 @@
++[
++ {
++ "pk": "1",
++ "model": "fixtures.article",
++ "fields": {
++ "headline": "Poker has no place on ESPN",
++ "pub_date": "2006-06-16 11:00:00"
++ }
++ },
++ {
++ "pk": "2",
++ "model": "fixtures.article",
++ "fields": {
++ "headline": "Time to reform copyright",
++ "pub_date": "2006-06-16 13:00:00"
++ }
++ }
++]
+\ No newline at end of file
+Index: tests/modeltests/fixtures/fixtures/fixture2.json
+===================================================================
+--- tests/modeltests/fixtures/fixtures/fixture2.json (revision 0)
++++ tests/modeltests/fixtures/fixtures/fixture2.json (revision 0)
+@@ -0,0 +1,18 @@
++[
++ {
++ "pk": "2",
++ "model": "fixtures.article",
++ "fields": {
++ "headline": "Copyright is fine the way it is",
++ "pub_date": "2006-06-16 14:00:00"
++ }
++ },
++ {
++ "pk": "3",
++ "model": "fixtures.article",
++ "fields": {
++ "headline": "Django conquers world!",
++ "pub_date": "2006-06-16 15:00:00"
++ }
++ }
++]
+\ No newline at end of file
+Index: tests/modeltests/fixtures/fixtures/fixture3.xml
+===================================================================
+--- tests/modeltests/fixtures/fixtures/fixture3.xml (revision 0)
++++ tests/modeltests/fixtures/fixtures/fixture3.xml (revision 0)
+@@ -0,0 +1,11 @@
++
++
++
++
++
+\ No newline at end of file
+Index: tests/modeltests/fixtures/models.py
+===================================================================
+--- tests/modeltests/fixtures/models.py (revision 0)
++++ tests/modeltests/fixtures/models.py (revision 0)
+@@ -0,0 +1,66 @@
++"""
++39. Fixtures.
++
++Fixtures are a way of loading data into the database in bulk. Fixure data
++can be stored in any serializable format (including JSON and XML). Fixtures
++are identified by name, and are stored in either a directory named 'fixtures'
++in the application directory, on in one of the directories named in the
++FIXTURE_DIRS setting.
++"""
++
++from django.db import models
++
++class Article(models.Model):
++ headline = models.CharField(maxlength=100, default='Default headline')
++ pub_date = models.DateTimeField()
++
++ def __str__(self):
++ return self.headline
++
++ class Meta:
++ ordering = ('-pub_date', 'headline')
++
++__test__ = {'API_TESTS': """
++>>> from django.core import management
++>>> from django.db.models import get_app
++
++# Load fixture 1. Single JSON file, with two objects.
++>>> management.install_fixtures(['fixture1'], verbosity=0)
++>>> Article.objects.all()
++[, ]
++
++# Load fixture 2. JSON file imported by default. Overwrites some existing objects
++>>> management.install_fixtures(['fixture2'], verbosity=0)
++>>> Article.objects.all()
++[, , ]
++
++# Load fixture 3, XML format.
++>>> management.install_fixtures(['fixture3'], format='xml', verbosity=0)
++>>> Article.objects.all()
++[, , , ]
++
++# Reset the database representation of this app. This will delete all data.
++>>> management.flush(interactive=False)
++>>> management.syncdb(verbosity=0, interactive=False)
++>>> Article.objects.all()
++[]
++
++# Load fixture 1 again
++>>> management.install_fixtures(['fixture1'], verbosity=0)
++>>> Article.objects.all()
++[, ]
++
++# Dump the current contents of the database as a JSON fixture
++>>> management.dumpdb(['fixtures'], format='json')
++[{"pk": "2", "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "1", "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 11:00:00"}}]
++"""}
++
++from django.test import TestCase
++
++class SampleTestCase(TestCase):
++ fixtures = { 'json': ['fixture1', 'fixture2'] }
++
++ def testClassFixtures(self):
++ "Check that test case has installed 3 fixture objects"
++ self.assertEqual(Article.objects.count(), 3)
++ self.assertEquals(str(Article.objects.all()), "[, , ]")
+Index: tests/modeltests/test_client/management.py
+===================================================================
+--- tests/modeltests/test_client/management.py (revision 4223)
++++ tests/modeltests/test_client/management.py (working copy)
+@@ -1,10 +0,0 @@
+-from django.dispatch import dispatcher
+-from django.db.models import signals
+-import models as test_client_app
+-from django.contrib.auth.models import User
+-
+-def setup_test(app, created_models, verbosity):
+- # Create a user account for the login-based tests
+- User.objects.create_user('testclient','testclient@example.com', 'password')
+-
+-dispatcher.connect(setup_test, sender=test_client_app, signal=signals.post_syncdb)
+
+Property changes on: tests/modeltests/test_client/fixtures
+___________________________________________________________________
+Name: svn:ignore
+ + *.pyc
+
+
+Index: tests/modeltests/test_client/fixtures/testdata.json
+===================================================================
+--- tests/modeltests/test_client/fixtures/testdata.json (revision 0)
++++ tests/modeltests/test_client/fixtures/testdata.json (revision 0)
+@@ -0,0 +1,20 @@
++[
++ {
++ "pk": "1",
++ "model": "auth.user",
++ "fields": {
++ "username": "testclient",
++ "first_name": "Test",
++ "last_name": "Client",
++ "is_active": true,
++ "is_superuser": false,
++ "is_staff": false,
++ "last_login": "2006-12-17 07:03:31",
++ "groups": [],
++ "user_permissions": [],
++ "password": "sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161",
++ "email": "testclient@example.com",
++ "date_joined": "2006-12-17 07:03:31"
++ }
++ }
++]
+\ No newline at end of file
+Index: tests/modeltests/test_client/models.py
+===================================================================
+--- tests/modeltests/test_client/models.py (revision 4223)
++++ tests/modeltests/test_client/models.py (working copy)
+@@ -19,10 +19,11 @@
+ rather than the HTML rendered to the end-user.
+
+ """
+-from django.test.client import Client
+-import unittest
++from django.test import Client, TestCase
+
+-class ClientTest(unittest.TestCase):
++class ClientTest(TestCase):
++ fixtures = { 'json': ['testdata'] }
++
+ def setUp(self):
+ "Set up test environment"
+ self.client = Client()
+Index: tests/urls.py
+===================================================================
+--- tests/urls.py (revision 4223)
++++ tests/urls.py (working copy)
+@@ -6,5 +6,5 @@
+
+ # Always provide the auth system login and logout views
+ (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
+- (r'^accounts/logout/$', 'django.contrib.auth.views.login'),
++ (r'^accounts/logout/$', 'django.contrib.auth.views.logout'),
+ )
addfile ./patches/patchlist
hunk ./patches/patchlist 1
+/usr/lib/python2.4/site-packages/django/db/backends/util.py (remove params for sql debugging...)
+/usr/lib/python2.4/site-packages/django/utils/simplejson/decoder.py (fix utf problems with json)
addfile ./scripts/mirror_prod_to_dev.sh
hunk ./scripts/mirror_prod_to_dev.sh 1
+#!/bin/bash -x
+DJANGO_PATH=/home/getzdan/myversion/django
+PROD_DIR=/home/raph/garden
+DEV_DIR=/home/getzdan/myversion
+# mirror database using dumpdb/installfixture
+PYTHONPATH="${DJANGO_PATH}:${PROD_DIR}" python2.4 ${PROD_DIR}/ghestalt/manage.py dumpdb auth > ${DEV_DIR}/ghestalt/gauth.json
+PYTHONPATH="${DJANGO_PATH}:${PROD_DIR}" python2.4 ${PROD_DIR}/ghestalt/manage.py dumpdb app > ${DEV_DIR}/ghestalt/gapp.json
+# get rid of auth.permission records b/c installfixture makes some wierd error [temp. hack for temp script?].
+perl -i -npe 's/,? ?{"pk"[^}]+?"model": "auth\.[^u][^s][^e][^r].+?}}//g' ${DEV_DIR}/ghestalt/gauth.json
+echo "DROP DATABASE IF EXISTS mirror ; CREATE DATABASE mirror" | mysql -u root
+PYTHONPATH="${DJANGO_PATH}:${DEV_DIR}" python2.4 ${DEV_DIR}/ghestalt/manage.py syncdb --noinput
+PYTHONPATH="${DJANGO_PATH}:${DEV_DIR}" python2.4 ${DEV_DIR}/ghestalt/manage.py installfixture gauth
+PYTHONPATH="${DJANGO_PATH}:${DEV_DIR}" python2.4 ${DEV_DIR}/ghestalt/manage.py installfixture gapp
addfile ./scripts/run_dev_server.sh
hunk ./scripts/run_dev_server.sh 1
+#!/bin/bash
+OLDSERVER=`ps -aef | grep 8001 | grep runserver | awk '{print $2}'`
+kill ${OLDSERVER}
+PYTHONPATH="/home/getzdan/myversion/django:/home/getzdan/myversion" nohup python2.4 ghestalt/manage.py runserver 0.0.0.0:8001 &
addfile ./scripts/stop_dev_server.sh
hunk ./scripts/stop_dev_server.sh 1
+#!/bin/bash
+OLDSERVER=`ps -aef | grep 8001 | grep runserver | awk '{print $2}'`
+kill ${OLDSERVER}
addfile ./static/images/ghestalt.png
binary ./static/images/ghestalt.png
oldhex
*
newhex
*89504e470d0a1a0a0000000d4948445200000105000000580806000000fcf1e20c00000006624b
*474400ff00ff00ffa0bda793000000097048597300000b1300000b1301009a9c18000000077449
*4d4507d7011a121b146d6570850000001d74455874436f6d6d656e740043726561746564207769
*7468205468652047494d50ef64256e000010d34944415478daed9d7bb855c575c07f17bd228a0a
*2824a2c820885131d84403220aa255a934629bf8481b8d494d1a12ada11a5b53153f53b5e6a1a1
*564d529368e2a335522a510b4a4b7cc4478b0f408a5161e28b800614441e5eb8fd63addbefe47a
*f69e39e7ec7deede87f5fbbef37d70f76366af3db3f6cc9ab5d680611886611886611886611846
*edb499080ca33938e73a1bed8fdefbdcebb963f9443b2320d819a6e80ca3017a99080cc330a560
*18862905c330e2d8d144601401e75c2f602cf02b10839a738eae7f1b71f2f3deffaa526e5dffae
*24245b530a464f36e43d80138129c064602fd4025fad311b61f939e7da2a8e275d672305a3500d
*79a436e229c078a0dda4522cf99952309acd0b268262cbcf0c8d86619852300cc394826118a614
*0cc330a56018862905c3304c291886614ac1308c6661ce4b3d84736e08701c70147020300cd803
*d805d8026c0056022f030b818781c7bcf75b73aa4f3fe00f8149c0e1c02060a07e38de015600cf
*693dee03deeebab66cb109ceb9c3f459c70023807d80be8877e006e0772af76781ff02e6039bab
*ddab15e3324a989024eb242b33fac08c8d4d6a8cbd80d38069888b6aadf25f05fc0cf8aef7fe8d
*8cea3414980e7c01d835f2b22dc03dc055c0926a1d2422cb506e6db85a4775cef5063e0f5c008c
*acb18cb5c04f816b81d7eb550e35665eea31f965a514f606fe18381a3804d80fd85d8fad03f6cc
*5029344bf9b465ac1026003701076570bbcdc0b7812bbdf79bebac4f9b7690ab809debac4727f0
*efc085fa65fdff0e5224a5e09c9b0cdc00ecdf60599b80abf5f77eadca617b510a1380af032735
*cf3ed12ca5908d7270ceed00fc837e8db31e992d013ee9bd5f51639d060077eb54210bd6015f04
*fea5088dbaab63aaecbf057c2de332ff1b980abc518b62288b52a8b723efa35f8805c01fd1d206
*cb199d0d2884de2aa7bfce69aa360a78ca3937ba863a0d041ec95021a0a3c2bb803f2990dd6047
*60760e0a01e008e029e08084b24bdde2ebe9cc53babe506c37d4ae18b451de0d9c9c73e5f602e6
*39e70e88a8533b30073838877a3c02dc5b9437e6bdef005ec9b1887d1003e4beada6186a550ae7
*e997af1fdb1d352b866bd4ce12e265e09bc0386088ceeff7452ce397034b23ee310898e59cdb25
*70de657adf34162146c7e15a97ddf58b782a702bb0beca35ab8033808e82bdb4bfd28e5b556f00
*d7eb346004d05f9fd7212b13372306c63486a8e26f6f25c550cb90761af04f05e89c3d58f63567
*c3a6db22bec89381fb03a76d042e05aef3de6f4bb9571b70aeda2542caf846effd5712eef321ed
*086946c5ef035fadecdc558c7603802b812f6bfbd90a9c00fc67684e5dc7bc3a78bf8877d11f78
*b262a8bf12b818b81dd8966613d0a9d6f7803303c55c91d4306b5c9189e98f9d19f6e9aab28dbd
*c124601eb043e0bc5f02b7216bd92bf56f7b03c7009f0526165b29cc686b74c9d339d707781ef1
*3b48e26d6092f7fe991a1af70895efe0408319e7bd7fa2caf57f8358cd93781049edd519d9b94f
*02ee00be03fc7d6c076eb652d0320f049ed051c3b94923801403e155c0dfa614b149a7642b024a
*a66594c26e6a43d82fe59cb5c0d93a5f0dd9236ed3a15a12bf410c68efd6398c9f00331ece77aa
*90ac189c731721ebd949bc071c57ade34634ee91c0636a47486281f7fed82ad72e10d924325eef
*1ddd119d73fb01af7aef3b6393acf68452d072f7079677252dade8a8b1cffa23e09c94536ed6d1
*53e995428c4d617a4021bca3f3e13911f7fa859efb4eca394369cc62fcd19e9a5ce86ac3f4c069
*5faf4721e80bfc35f0a5c069139d73e3aafc7d54e0baa7eba8cf2bdefbceaec65564ef3eeffdf2
*aefa55d6b3863a4f077e9b72fc6c12fc71ca665b082985dec0f98173ce0596d550e632644d3b8d
*0bb4ec7abef23764338da88b53800f079efde6061bf72c9d9ea551ed8bb547e09abd30d2e4feb6
*da0e92e8037caa159e35a4144e0606a41c5f82585f6be56e2adc63ab3000f17f282889d38b3f0f
*5c787d46b10bd7058e4f75ceedd4ed6feb03d79c695d3fc81d3afd4be2d3db8352382170fc6775
*96db89587f1b293bef8e5fd36841a70ec7a79cd2c1ef7bfc35c2fd881761127d11e36e25ab02f7
*bc14185dd6216f93460beb9060b0248e4a1ae196499e21a5f0f1c0f1471b283b74edc74ad6668e
*d42164128feb10348bc6b985e4f5f72ebadb151e0f9cdf1778a852b19962a8ca9329c776063e51
*f6070c854e875ac5f206ca0ef9eb0f2b992c0f0f1c7f3c87c6796a0d4af53ed2ade75d7685b9c0
*8dc025c0fa56deba4dbd4e8f4196ca3f8e044c7d188916ed005623e1e28f2251a1cb9130f63446
*23de9d2dab1442c6a9b50d94bda6c1b28b4668d5e3b98ccbfbdf1a95ea6c6423910323468f5f05
*fe5415c36dc0b656520e1a2e7e3ef039926d66edc84ad850c4a5ff5ac4c07b67e0f607975d3e96
*64253b42239bdb9d73b737b13e83bb4d39b63ae7a623cbc231f692bd811f234b717f87c635c4ae
*eb175419f4415610cea7bed5ad63f8a0ada63bc3cbde904336857702c7fb3750f68006cb2e1a83
*0b569fbe556c11f723f114b5702812eff20c1205d9e69ca3eb572285300ac9a47411752f7747f1
*a156570aa14f4223492b425fd615c516dd079625f72c5805ab367ceffd95480056ad1ca6f3ea85
*48c05057672b8342381ed9e27e64138a1bd4ea4a21e4e536be81b2c7375876d1e853b0fa6c49d4
*f4de5f8a3890d593b5e90f903898dbbb146191470d9af1ea5ec45dbf19ecdaea4a615ee0f89fd5
*596e5bc4b5f34a26cba26da99e6a04f6deff1059575f5ae7fd3fa38a7b4c51470dceb9613aba89
*51d8ab81998881f5009ddeb6abe21b8d78eece2321b2b2829d5b5d29fc82f4558243a9cf8bebd3
*a4fbe2af211c7a5c343617ac3e2f854ef0de2fd42fffa5843d1eabb11f12b939b5688a4143ce7f
*1231addb80181e8722f91766a9ecd622cb926bbcf78bbcf7ffecbd3f91b053dd4e65570a3b4634
*f47f24dd38f5436031f1f10f1f017e10386766013b5988f7025f89fe59392f65893a427dd33977
*339267e0cb350e817b033f47b254cfea520c0558a13893f04ac1cbc872e3d204d954fbdbfc5677
*ea8a8992fc0ef05acaf13d10234e4c96a1297a6e9a0fc2abc0774b28cbb702c70b6d95f6debfe5
*bdbf087158bb5abfa0b1ec80f8338c2ad088e11b81e3bf43120e472b84ed8518a5b01ef1844b0b
*e4e98f187316e8b9c3914d4d76d17f9f836caa3187f465ccad7aeefa12caf2d5c0f12165780855
*0e97e87bbb29f0de2bd95547958dd256652a50ebd4e148c24e445f499a62955c21d41ab3539752
*00f1898fc9713001f8910a7b83fe5ed2bf4d8cb8fe02c23efd45e5c5c0f15279ba79ef5779efa7
*a9cd21d6457b62e590bdced1421686ba2981e34f03ffdaa21ffa86e5574be2d6b9393e48a72a9d
*1b4afc32423ef14796f1a1bcf78b91558a8b23470d5303c73b9aa014c6068edf494206a3128c12
*3a8aa21476457ce7f3601de229777dc93574e86b3a49372729a362e8f4de5f0b9c4e381d586844
*b82970bc7f06550e39293d54e27696bbfc6295c21564b3dd5977ee47963567975c21e0bd7f1ec9
*2f99c4206443d9323fe33d11a3b97d02c74381704333a86a288bd46b257e0db9cb2f46290c46f6
*7bc872aaf01fda414e26df0d3b9acdacc0f10b5ae01943e9e442312dab03c7b308280af90ad41d
*57a31beaf424b9cb2f46297c2e42c8df42f685b8030911ee72fce8d07f3fa7c7a62156f8c954ec
*13d04284fc2f263be78e2df933867268bcd7e0f559d85e427518d8c0bdf72fb8fc1b965f4ce8f4
*8981e3b3914d664196b0b65bbcf7cb9c730fa8d24be216e7dce1defb35257dcc50c0cf6f02c743
*6ed55928cddf22bb3e257134f5a7c63ba387e59fbbfc62460a87048e5f8351c925a41be38601f7
*e94e4b75e39c1bec9cfb37e75cbf1aaf3bc43977ab736ea73a43a043cb7d4f058e870cb2c3a892
*ebb2c63a86bc6bcfab53e6c391d0eb9ea42ef9059eab66a510ca80b4d8f4c0ef8d169e25bcbdde
*58e051cd00544fe31c87ec78341571338fbdae8f7e21cf4262165c2d9d4eb79ebbac41bbcaa3c8
*9679695c51ad6dd6a01842e9d08e022e8ce920157fdf17b185f5741464ddf28b550c3117be1938
*3ec254c107b838e26b7510b0d8397761acf1ca39d7cf39f76d242d589787e4a79c735f8cacd7cc
*8a91df58647bbbcb51e360daa8c13977a8969be6aefd82769c34a5f91ef040a09ee380ab02b2d8
*df3937db3937a672c4a3f5bf274216d7a6299f4a3938e74e45fc507abcad67253fb58dcca65b94
*ab732eca25723eb29764da70714a84f2c888c6f67a6c5659ba35fc1384adf100af234145731043
*d24a249ea01f1289f8317dd1a7247ca93602877bef97a6d4e774e0ae84c39b90b5fb0790d894d7
*100bfd0024a1e919488051c8067512154e6e297b334e22ce7375b676de453a251ba8b2380d0971
*6e47f61039adcab5f712178ff302b2cc3a1f5909eb50b98fd011c5591153e8ee24b58b86b77cd3
*6def72955f4c07fa3c704be09cb5483ebfb94842d137093b59b4b452d0c63f46bf9cfd9aa02d97
*004778ef3755fbaa22e9d476cfb1fc6ba8d88435624fc9d0c72696adda81bb17f8117de6acf31b
*3c86a4ba1bdd534a216ff9c54c1fee24ecd7df1f49f03957b5ed461540da6f9b2a9397f4bacb55
*33b7927de1497d716f34a1b88d29f69f41c40736d5c34d8881b516be4436816f3b50ddff6319f0
*97193fe7bb48c6aa22b8e3e726bf5e918ded801c1eaa4dbfa0c391c41533d488b208d9acb3ad45
*14c3334850d1833915b10d71113fda7bbf2aa10e4fe8dcf17f322e7b9336a8695d5fc1d88d66bd
*f72f21b90cd665508f2f248cc66e05fe02783f8332d6eb347929928a6e6d0fb7abdce417a3143a
*9bfcbc87221973e653be0d61925ee06aeffd093a3f7d3dc35b3f098cf7de7fcd7bbf3950871711
*c796e91935e88791bd2ebe173b65a852a70548ac44a323a917936c37defb5b908d7a1a51884b55
*76bfacf850de528076958bfc7a154c2154722c62f43a8816c17bff53c4ea7b2ee9db8f85e68073
*8129defbb1defbc76b28bfc37b7f1de21f3f9df08632d57848bf98132ba795f54617ea486aa48e
*14dfadf1f2c5c067b5d32f4f9a7f7bef1721ab2de72069de6b992e5c86185b9fef76ec46c2f91a
*9b3512cd547e4943f4d391cd40d276378ed96d280b5623e9c557ca7fcb63680ce164dd6b12b2b2
*7020e237d00f494eb31571d77d53ed344b90959eb9defbb7b27a425d6a3c4e3bcd4864a97337fd
*60acd1f29f4712e83c88a4306b4811a4d46537adcb4988957ca0feda7598fc86da0a9e4592a82e
*4c520481728e50b91fad53e33dd51eb301d98877a1deffe7491dad8821d659c82ff1de3a7f0a19
*0ad121d5c548c28a253a347e37e2da5a7f776118468f31275221d44b9b7e893eaa06aaa72315c3
*687b3586d17c3e11e898792cc5b421a9b5b705cabed25e8f61e44f7743e36702e7bf95431d3a11
*0bf6ccc079c7dbeb328ce6f35ce06b3d2ac7b20f0a94fd8abd1ec3683eeb021d33cffd127b07ca
*de6cafc7309a3f7d086dd1dd37c7ba84b6f7da64afcb309aaf145606ce1f93635d42710fbfb6d7
*6518cde7cec0103eaf9da0db110fbfb4b2afb6d76318cde714c2fe0259a7a3da098975482bb383
*7c82b20cc388984e2c8a500c33236c0031659d80c4bc87cabbc95e8d6134876abefb47221170a1
*2c3b5dd97a1e41022b5e41e214d621a1aadbf41e3b231e8c0311bffa91885ff671487c45886588
*53d57a7b5d86d1739c47f6f10bf5fc5e239bcd410cc3c8806ff4b042584acf6fbc61184637ce22
*9fa8c7d0ef27e49b4fd0308c06188e84466f6b823258004c30911b4639188164ec5d96b12258a4
*f73dd8446c183d4fbd99838620de8d87e9486228b2ba3000c91ad48e2c39be0f6c41560ed62059
*6d5620d97b9e45f2e6bd69afc1300cc3300cc3300cc3300cc3300cc3300cc3305a95ff03ac27c4
*ecc7b280ac0000000049454e44ae426082
addfile ./static/images/ghestalt_he.png
binary ./static/images/ghestalt_he.png
oldhex
*
newhex
*89504e470d0a1a0a0000000d494844520000012c0000005808060000004fb9ca1600000006624b
*474400ff00ff00ffa0bda793000000097048597300000b1300000b1301009a9c18000000077449
*4d4507d7011b0b2d35035b0e340000001d74455874436f6d6d656e740043726561746564207769
*7468205468652047494d50ef64256e00000d804944415478daed9d79901f4515c73f6bb24b4242
*0e20842480e188c8210104020a8840a52c15b4103c90db0818452308444a654104454001012f02
*06391404a40ac29970844b4024184e09b01c41c2261092cdb5c9fac7ebadaccb6fde1cbff91df3
*dbefa76a6babb6677b66fa4dbf7efdfaf56b104208218410420821841042082184104208218410
*42082184104208218410420821841042082184104208218410a27634a90952d3a5f614a236f457
*1308514b5af59c29f8903e1821445190c212424861092184149610420a4b0821a4b08410420a4b
*082185258410525842082185258490c2124208292c2184c8445fdbfcbc1b7024b037f0616000d0
*0ecc016e02a6031dfa2c24a73a6338b025b0153016180d8c024602c3c2cf7a400bd00cf4035601
*2b8025c082f0330f781e780a7804589ac3b32d00362cf1f7d5e1de8bc37d9f01ee01669423bba2
*a4432937a5cb18e052e0c098ebde008e02eecef82c95a2e73b5e0d1cea5c7b1570440ef71c0abc
*1b51f63e30a4cee504b03274e052f403d6a4688f759d0ebe2c942765bdd0914bb1145a0727540a
*e5d01994d65f816b8177fccb5ba30aee053e95e2be4b805f03e786ef4853c212a3f513093a4177
*8799017ca98edf6732f0aa537e38f0951ceeb39953f67a41e4e475889694cf37c2297b27655da3
*9cb2b74afc6d6e8566577b0217016de1f70619ea49fb6c83811f05596f2785f5ffec04dc194ce7
*3482bc0af8689dbed37bc061c1e48ee2b7310aa7de1456a5e4b4c4296b4ef98c9e85d35e4085d5
*9381c009c0b3c00129fff7998cf71c07dc0f6c2f85656c10fc1d43330af0c23a7eb7d9c0394ef9
*b0d099cb91efa63153b222c8a9512cac67aaf45d8d006e068eafa085d593f581bf07ababcf2bac
*df600edbac4c0476a9e3f73b0378d429df1b985a000bab9272ca536135b285d55b275c027ca10a
*0a0b600be0b4beaeb0c6f0413fce42e0646073601d601be0f2987aa6d4f13b76025f8f99f6b496
*a17437ab8285556939e53925ccd3c21a9d4161b5030f027fc47c4047009f063e16ea1b12daab1f
*302828d82d817dc2b517637ea3a47a611ab071826b17600b2a3d7f9ac3f47e1fe097c0a2983a26
*632bc189fc008dc81bd8ea477767781c73e6ceef71cd73c0246ce5e7bb11f57c2608afe76a52a5
*5656b3ac3ebe147c0f57389df21acc47b4344785f57a01e4d4481656da55c28ef0d38e8514105c
*04dd16cd71a12d07c44cd7ce25db8a7327f076f8b90f380fb83e58fda5181a94dbed7d794a3815
*8b43990becdfab13f4e434cc911de55fd9adcedff3caf03144318e6cfeb86af9b02a29274f61ad
*93a38595a7c2fa6f85bf9779c0a9c1727d2ce6da43818fe470cfb73167be37d0edd997a78400af
*00670107391f3a61e4bec129dfa300ef7a5cccc7f08dd00e4969895158af14444e4b7254581be6
*38254c6b6155aa7fec05cc74aee9071c9bd3fd1603bf73ca13ad16367a58c359c00b09aebb37c6
*42a9771661f1575e20e41f627c27bddfb99fe3b3585410397916d68094cf582d0bebad2a7e372b
*b058b6f9ce355fcbf17e0f667441f41985959467eb5861ad4c78ddbdc1e7e0f924a693cc07b763
*c6b6aa3739790a6b608d2cac8158d84929baaa3025eccdbb98133f8ad198633f0f5e72ca12c5e0
*496119af95abf9cba47fcc2898949f608eeb28f6034e4a50cfee4ed9a30592d32ae7fa4129efbd
*514e16d628df526e5d598376bd3666fabc574ef7f1da69881456723c610daec2fdd7cba933acc2
*a2e0bd8efab3180b0a6cd52d8ad9059253674e0aab3fb60119679a5cb4e9604f96613b0da2c8cb
*c2f206df443e4529acb502cb6b24ce8217e5fd668a7ab6c76296bc18a3162cd4216a4ab40b9615
*20aa9dee29909c56661c247ab39d33955e4aba90917a5458e0af186e9dd33dbc0124515c9c14d6
*5adf4114eb56e1fede26d0e712d6714898ae7d32c1b5db00e7479479fe8cdbc8272549b5e4b4b4
*dc2948c08bfa6e4bf90e9ec29a5fc3b6fdb75336ba5e3aaa14563ccd55b8c704a72c89cfe8abc0
*752995ebb780cff7fadbe498ce7959c1e4e439dd8727ac771070b453fe7ccae7f43affab356c3f
*cf92df480a4bf4ec68873b16c51d31ffff716cf52f8b2ca7b17675660ab67d238ac76b3c1dcc82
*e7ff4b9a4ae51c2c695e96a9545a0bab960acb9b8e0ea81781f697bea839539c0e312be6236ec1
*b65c64b50247007fc67c435e5a91d5c1222b1a0bcab01a9ab11c5171990b6e49f94c9b645058e5
*26464cc2d22228aca258585d35bc776705ebde0938336674f79884f9a3a25888edd39be35cb33f
*f139904ec70f97a85739795b88c63883c091984f274e59dd8aeffb2985b783e0a51ab6dff22a28
*c53e6361ad24fd568abcdaa152713123b13c50039cce7077cc603335c6bad8358cda7383c2c932
*525e86854214514e8b303f56a915c1b1e159870625321edb807b00d1819d3d590c7c27e5f33739
*0aab83b51b956bc18a222882a228ac154e4768ca61646faeb2200786a944541ea8f7127486fd9d
*8fbf0b4b3dd33dc5980b9c12a63869380b0b462db29c5e04768e98122ecff81cabb08dc1afa4fc
*bf2d880e27990bad6b100d31255c91f1234e8a67792ccbf95d9a30bf939705e2d8049de1cb4ed9
*edc05dbdfe763196073d09eda1fe1fa75432f528a7bcb3752e02be182ce0b4ece094cd913a6a1c
*85f5ae53964760675e91e6493805fff084f3b01c5171eceb945d1af1f7a3b1541f1eb3b1b8b0eb
*1b444e4fe624b72e2c7464072c1e2d0bbb3a658f481d358ec2f23684ae9f43fd9ecf62418eefb1
*1bf053a7fc4e92a5351e8565e48cb272ee70daf19898bac791eef8ab7a9753b97b1fdfc7c23fc6
*63990bca495e38d129bbaf01f5cbf030485e07fc871c828e8be2c3f23ac268ca5f5d19e394bd9d
*d33b749ff21235359a1ffc22ab13d4b5ad53f634fe5ec25bb19cdddf8e281f896def39b041e4f4
*58e828492dbc65a10d1fc2c24aee24bbafab271b63abc211b26f7db18114d578e0442ca0b925cf
*8a8b6261bdec946d9143fdde52735e1fd231f8d91b27a5987e7af52499029d8cefdb39806c7157
*f528a795f849ea7e811dca3a313ce3206ce7c1f7b18591e539c9ff28a7bfdd4e633018cbbbf624
*965ab925c3ff3784c2f24ee6d83187fabd58a6e773a8bf3fe6c08ee286947e91cd9db2244be3cb
*8235e739c9cf27fdd98cf52aa71b6214dd9fb0458a97a94c2cd93af8315d7f6b0065350a4bd037
*89ec715bbb368ac2f282f3f2c8d5e3a541ce63f5665ffc08e7b353d6e7e5e84aba19f729fce395
*0662591d5a1a404e37129d7ef99b55f87ebf871fc27257c195d5b0f00e3b9459cfee8da2b0fee5
*7c703bc74c15e21849f45158eda48f642ec57e4ed96cd2af64e5a1b0007e15d35976c262b18a2e
*a725d869d8a59880c5ac558af1d8716b514cab51d2bebc68c2b6772539767e758c051b7b7e4251
*145627d11b6f9bb02c0359994c74fef259394d11c63b653332d49797c2eac2b6a178beb393b0f3
*ef8a2ea78b88deb5707186e96f12c604eb2e2a5874257041c1adabe381cfc558ddc784c1aa19f8
*8473ed84465158007f8931b9b31c47b4397ecae0e9393dbba76066a5acab3fd13bfe5793fe08ae
*f9c1efe07d23d3499e8ea55ee5f426d191fec3c3c0b1758edfeb56c0fdf88b0dd3a0f5758acb48
*e0e7ce60786618acafc0c241bac26c226ae0d828a6bd0aa5b06e74ac878198d37aab14f50d0d75
*0e722c95db72146c14afa5ac6b13476e6f902c2ca2373763ab3bde3d7fdf00723a9de84589b1c0
*3ff8e049d459380cf8674ce76bc3ce072c32ad4427423c29b477ef98be15a16da2d8bd51145627
*7e66832db120c18313d4b50df000fecad5d48c9dbf145e62bdb4715e794d077b3305ffa8ad8389
*0f3aad773975604ef6a8c0d8215890e303d842499ad5aea630759e8dc5db7951f96bb03087c505
*565663b1f32e4b710de61f8de291bea0b08209ed9e4db73eb6a5e4216c3fdeb8a02cd60d0d7c08
*7642c81cfcc4fa33c37579e1653048eb70ad94c2eac0421dbca0d30b83c229b29c66127de47d37
*7b62beb8b6308d3c1c5b011b89ed676cc68efdda160b8ebc000b8998497c8aeaaea03467516ca6
*523a087a117042ccff3e9c5561152d815f57f8781ec60f13d883ec2736b7858f304ff2cc275429
*8505f004969d212a0fd760e0ead0a13b0b2ca74b423b9e9260fa7d42cedfc294a0d08bcc986021
*96e26c2c0f1b192dac1dc3a0b0bc112c2c30e7dd6713344a16166051de0beaf8fd2ba9b0c00e63
*f5aca309c1375174399d8a45fc572ba5cb62e020d2a7f8a9477e10316b682759deff36a20fdc68
*c6d27e37c494b09ba783e9f8428e75b605cba1ded37c545a61adc1b65578c7d1ff30b455d1e574
*1e761047a507a8c7b018b29b1a40598d08d3f8289741d20dce99a685453e84e2c530da5f4ef9b1
*52d76041922f14e0bd2badb0c0562ebdad24fd30c7f2d00690d30ccc877601beff2e0bf3b00c0f
*13c86f4f6aad3991d28b48efe31f6292665ad8900a0b2cffd2242c18ed16d2adea759f4833118b
*745e589077deb40a0a0b2c27d7954ef958a2f36e154d4eef61cbf0e38033282f55714768bb83b0
*60d4eba86daefb3c194674f0ef65f8f9d072b1b09a682c46636951f6c0b6828cc0820257870fbd
*1ddb43f770e804f31092536976c6f297ed82ad546e103aec506cc16171f859083c1b9ef7a96039
*7424bf4d6b4144561fcfd9a4be23841441519e5307a90a210a83149610420a4b0821a4b0841052
*584208218525841052584208292c21841042082184104208218410420821841042082184104208
*d190fc0f37c504d836b2cd590000000049454e44ae426082
addfile ./template/__init__.py
addfile ./template/loaders/__init__.py
addfile ./template/loaders/i18n_app_directories.py
hunk ./template/loaders/i18n_app_directories.py 1
+# Wrapper for loading templates from "template" directories in installed app packages.
+
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.template import TemplateDoesNotExist
+import os
+from django.utils import translation
+
+# At compile time, cache the directories to search.
+app_template_dirs = []
+for app in settings.INSTALLED_APPS:
+ i = app.rfind('.')
+ if i == -1:
+ m, a = app, None
+ else:
+ m, a = app[:i], app[i+1:]
+ try:
+ if a is None:
+ mod = __import__(m, '', '', [])
+ else:
+ mod = getattr(__import__(m, '', '', [a]), a)
+ except ImportError, e:
+ raise ImproperlyConfigured, 'ImportError %s: %s' % (app, e.args[0])
+ template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
+ if os.path.isdir(template_dir):
+ app_template_dirs.append(template_dir)
+
+# It won't change, so convert it to a tuple to save memory.
+app_template_dirs = tuple(app_template_dirs)
+
+def get_template_locale_sources(template_name, template_dirs=None, locale_fix=None ):
+ for template_dir in app_template_dirs:
+ if locale_fix:
+ yield os.path.join(template_dir, locale_fix, template_name)
+ yield os.path.join(template_dir, template_name)
+
+def load_template_source(template_name, template_dirs=None):
+ if translation.get_language() != settings.LANGUAGE_CODE[:2]:
+ for filepath in get_template_locale_sources(template_name, template_dirs, 'locale/'+translation.get_language()):
+ try:
+ return (open(filepath).read(), filepath)
+ except IOError:
+ pass
+ raise TemplateDoesNotExist, template_name
+ else:
+ for filepath in get_template_locale_sources(template_name, template_dirs):
+ try:
+ return (open(filepath).read(), filepath)
+ except IOError:
+ pass
+ raise TemplateDoesNotExist, template_name
+load_template_source.is_usable = True
addfile ./template/loaders/i18n_filesystem.py
hunk ./template/loaders/i18n_filesystem.py 1
+# Wrapper for loading templates from the filesystem.
+
+from django.conf import settings
+from django.template import TemplateDoesNotExist
+import os
+from django.utils import translation
+
+def get_template_sources(template_name, template_dirs=None, locale_fix=None):
+ if not template_dirs:
+ template_dirs = settings.TEMPLATE_DIRS
+ for template_dir in template_dirs:
+ if locale_fix:
+ yield os.path.join(template_dir, locale_fix, template_name)
+ yield os.path.join(template_dir, template_name)
+
+def load_template_source(template_name, template_dirs=None):
+ tried = []
+ if translation.get_language() != settings.LANGUAGE_CODE[:2]:
+ for filepath in get_template_sources(template_name, template_dirs, 'locale/'+translation.get_language()):
+ try:
+ return (open(filepath).read(), filepath)
+ except IOError:
+ tried.append(filepath)
+ else:
+ for filepath in get_template_sources(template_name, template_dirs):
+ try:
+ return (open(filepath).read(), filepath)
+ except IOError:
+ tried.append(filepath)
+ if tried:
+ error_msg = "Tried %s" % tried
+ else:
+ error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
+ raise TemplateDoesNotExist, error_msg
+load_template_source.is_usable = True
}