Removed some unused code
- Legacy-Id: 1827
This commit is contained in:
parent
d90a550165
commit
4fd33bfda1
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,2 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
|
||||
from form_decorator import form_decorator
|
||||
import BeautifulSoup
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
|
||||
## formfield_callback generator
|
||||
## http://www.djangosnippets.org/snippets/59/
|
||||
def form_decorator(fields = {}, attrs = {}, widgets = {},
|
||||
labels = {}, choices = {}, querysets = {}):
|
||||
|
||||
"""
|
||||
This function helps to add overrides when creating forms from models/instances.
|
||||
Pass in dictionary of fields to override certain fields altogether, otherwise
|
||||
add widgets or labels as desired.
|
||||
|
||||
For example:
|
||||
|
||||
class Project(models.Model):
|
||||
|
||||
name = models.CharField(maxlength = 100)
|
||||
description = models.TextField()
|
||||
owner = models.ForeignKey(User)
|
||||
|
||||
project_fields = dict(
|
||||
owner = None
|
||||
)
|
||||
|
||||
project_widgets = dict(
|
||||
name = forms.TextInput({"size":40}),
|
||||
description = forms.Textarea({"rows":5, "cols":40}))
|
||||
|
||||
project_labels = dict(
|
||||
name = "Enter your project name here"
|
||||
)
|
||||
|
||||
callback = form_decorator(project_fields, project_widgets, project_labels)
|
||||
project_form = forms.form_for_model(Project, formfield_callback = callback)
|
||||
|
||||
This saves having to redefine whole fields for example just to change a widget
|
||||
setting or label.
|
||||
"""
|
||||
|
||||
def formfields_callback(f, **kw):
|
||||
|
||||
if f.name in fields:
|
||||
|
||||
# replace field altogether
|
||||
field = fields[f.name]
|
||||
f.initial = kw.pop("initial", None)
|
||||
return field
|
||||
|
||||
if f.name in widgets:
|
||||
|
||||
kw["widget"] = widgets[f.name]
|
||||
|
||||
if f.name in attrs:
|
||||
|
||||
widget = kw.pop("widget", f.formfield().widget)
|
||||
if widget :
|
||||
widget.attrs.update(attrs[f.name])
|
||||
kw["widget"] = widget
|
||||
|
||||
if f.name in labels:
|
||||
|
||||
kw["label"] = labels[f.name]
|
||||
|
||||
if f.name in choices:
|
||||
|
||||
choice_set = choices[f.name]
|
||||
if callable(choice_set) : choice_set = choice_set()
|
||||
kw["choices"] = choice_set
|
||||
|
||||
if f.name in querysets:
|
||||
|
||||
kw["queryset"] = querysets[f.name]
|
||||
|
||||
|
||||
return f.formfield(**kw)
|
||||
|
||||
return formfields_callback
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
|
||||
##
|
||||
## django form wizard
|
||||
## http://code.djangoproject.com/ticket/3218
|
||||
"""
|
||||
TODO:
|
||||
!!!! documentation !!!! including examples
|
||||
|
||||
USAGE:
|
||||
urls: (replace wizard.Wizard with something that overrides its done() method,
|
||||
othervise it will complain at the end that __call__ does not return HttpResponse)
|
||||
|
||||
( r'^$', MyWizard( [MyForm, MyForm, MyForm] ) ),
|
||||
|
||||
template:
|
||||
<form action="." method="POST">
|
||||
FORM( {{ step }} ): {{ form }}
|
||||
|
||||
step_info : <input type="hidden" name="{{ step_field }}" value="{{ step }}" />
|
||||
|
||||
previous_fields: {{ previous_fields }}
|
||||
|
||||
<input type="submit">
|
||||
</form>
|
||||
|
||||
"""
|
||||
from django.conf import settings
|
||||
from django.http import Http404
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template.context import RequestContext
|
||||
|
||||
from django import newforms as forms
|
||||
#import cPickle as pickle
|
||||
import md5
|
||||
|
||||
class Wizard( object ):
|
||||
PREFIX="%d"
|
||||
STEP_FIELD="wizard_step"
|
||||
|
||||
# METHODS SUBCLASSES SHOULDN'T OVERRIDE ###################################
|
||||
def __init__( self, form_list, initial=None ):
|
||||
" Pass list of Form classes (not instances !) "
|
||||
self.form_list = form_list[:]
|
||||
self.initial = initial or {}
|
||||
|
||||
def __repr__( self ):
|
||||
return "step: %d\nform_list: %s\ninitial_data: %s" % ( self.step, self.form_list, self.initial )
|
||||
|
||||
def get_form( self, step, data=None ):
|
||||
" Shortcut to return form instance. "
|
||||
return self.form_list[step]( data, prefix=self.PREFIX % step, initial=self.initial.get( step, None ) )
|
||||
|
||||
def __call__( self, request, *args, **kwargs ):
|
||||
"""
|
||||
Main function that does all the hard work:
|
||||
- initializes the wizard object (via parse_params())
|
||||
- veryfies (using security_hash()) that noone has tempered with the data since we last saw them
|
||||
calls failed_hash() if it is so
|
||||
calls process_step() for every previously submitted form
|
||||
- validates current form and
|
||||
returns it again if errors were found
|
||||
returns done() if it was the last form
|
||||
returns next form otherwise
|
||||
"""
|
||||
# add extra_context, we don't care if somebody overrides it, as long as it remains a dict
|
||||
self.extra_context = kwargs.get( 'extra_context', {} )
|
||||
|
||||
self.parse_params( request, *args, **kwargs )
|
||||
|
||||
# we only accept POST method for form delivery no POST, no data
|
||||
if not request.POST:
|
||||
self.step = 0
|
||||
return self.render( self.get_form( 0 ), request )
|
||||
|
||||
# verify old steps' hashes
|
||||
for i in range( self.step ):
|
||||
form = self.get_form( i, request.POST )
|
||||
# somebody is trying to corrupt our data
|
||||
if request.POST.get( "hash_%d" % i, '' ) != self.security_hash( request, form ):
|
||||
# revert to the corrupted step
|
||||
return self.failed_hash( request, i )
|
||||
self.process_step( request, form, i )
|
||||
|
||||
# process current step
|
||||
form = self.get_form( self.step, request.POST )
|
||||
if form.is_valid():
|
||||
self.process_step( request, form, self.step )
|
||||
self.step += 1
|
||||
# this was the last step
|
||||
if self.step == len( self.form_list ):
|
||||
return self.done( request, [ self.get_form( i, request.POST ) for i in range( len( self.form_list ) ) ] )
|
||||
form = self.get_form( self.step )
|
||||
return self.render( form, request )
|
||||
|
||||
def render( self, form, request ):
|
||||
"""
|
||||
Prepare the form and call the render_template() method to do tha actual rendering.
|
||||
"""
|
||||
if self.step >= len( self.form_list ):
|
||||
raise Http404
|
||||
|
||||
old_data = request.POST
|
||||
prev_fields = ''
|
||||
if old_data:
|
||||
# old data
|
||||
prev_fields = '\n'.join(
|
||||
bf.as_hidden() for i in range(self.step) for bf in self.get_form( i, old_data )
|
||||
)
|
||||
# hashes for old forms
|
||||
hidden = forms.widgets.HiddenInput()
|
||||
prev_fields += '\n'.join(
|
||||
hidden.render( "hash_%d" % i, old_data.get( "hash_%d" % i, self.security_hash( request, self.get_form( i, old_data ) ) ) )
|
||||
for i in range( self.step)
|
||||
)
|
||||
return self.render_template( request, form, prev_fields )
|
||||
|
||||
|
||||
# METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ########################
|
||||
|
||||
def failed_hash( self, request, i ):
|
||||
"""
|
||||
One of the hashes verifying old data doesn't match.
|
||||
"""
|
||||
self.step = i
|
||||
return self.render( self.get_form(self.step), request )
|
||||
|
||||
def security_hash(self, request, form):
|
||||
"""
|
||||
Calculates the security hash for the given Form instance.
|
||||
|
||||
This creates a list of the form field names/values in a deterministic
|
||||
order, pickles the result with the SECRET_KEY setting and takes an md5
|
||||
hash of that.
|
||||
|
||||
Subclasses may want to take into account request-specific information
|
||||
such as the IP address.
|
||||
"""
|
||||
data = []
|
||||
for bf in form:
|
||||
if bf.data is None:
|
||||
d = ''
|
||||
else:
|
||||
# Hidden inputs strip trailing carraige returns
|
||||
# so we exclude those from the hash.
|
||||
d = bf.data.rstrip("\r\n")
|
||||
data.append((bf.name, d))
|
||||
data.append(settings.SECRET_KEY)
|
||||
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
|
||||
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
|
||||
#pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
|
||||
pickled = str(data) #XXX
|
||||
return md5.new(pickled).hexdigest()
|
||||
|
||||
def parse_params( self, request, *args, **kwargs ):
|
||||
"""
|
||||
Set self.step, process any additional info from parameters and/or form data
|
||||
"""
|
||||
if request.POST:
|
||||
self.step = int( request.POST.get( self.STEP_FIELD, 0 ) )
|
||||
else:
|
||||
self.step = 0
|
||||
|
||||
def get_template( self ):
|
||||
"""
|
||||
Return name of the template to be rendered, use self.step to get the step number.
|
||||
"""
|
||||
return "wizard.html"
|
||||
|
||||
def render_template( self, request, form, previous_fields ):
|
||||
"""
|
||||
Render template for current step, override this method if you wish to add custom context, return a different mimetype etc.
|
||||
|
||||
If you only wish to override the template name, use get_template
|
||||
|
||||
Some additional items are added to the context:
|
||||
'step_field' is the name of the hidden field containing step
|
||||
'step' holds the current step
|
||||
'form' containing the current form to be processed (either empty or with errors)
|
||||
'previous_data' contains all the addtitional information, including
|
||||
hashes for finished forms and old data in form of hidden fields
|
||||
any additional data stored in self.extra_context
|
||||
"""
|
||||
return render_to_response( self.get_template(), dict(
|
||||
step_field=self.STEP_FIELD,
|
||||
step=self.step,
|
||||
form=form,
|
||||
previous_fields=previous_fields,
|
||||
** self.extra_context
|
||||
), context_instance=RequestContext( request ) )
|
||||
|
||||
def process_step( self, request, form, step ):
|
||||
"""
|
||||
This should not modify any data, it is only a hook to modify wizard's internal state
|
||||
(such as dynamically generating form_list based on previously submited forms).
|
||||
It can also be used to add items to self.extra_context base on the contents of previously submitted forms.
|
||||
|
||||
Note that this method is called every time a page is rendered for ALL submitted steps.
|
||||
|
||||
Only valid data enter here.
|
||||
"""
|
||||
pass
|
||||
|
||||
# METHODS SUBCLASSES MUST OVERRIDE ########################################
|
||||
|
||||
def done( self, request, form_list ):
|
||||
"""
|
||||
this method must be overriden, it is responsible for the end processing - it will be called with instances of all form_list with their data
|
||||
"""
|
||||
raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)
|
||||
|
|
@ -44,7 +44,6 @@ from ietf.idtracker.models import Acronym, IETFWG, InternetDraft, Rfc, IDInterna
|
|||
from ietf.idindex.forms import IDIndexSearchForm
|
||||
from ietf.idindex.models import alphabet, orgs, orgs_dict
|
||||
from ietf.utils import orl, flattenl, normalize_draftname
|
||||
import ietf
|
||||
|
||||
base_extra = { 'alphabet': alphabet, 'orgs': orgs }
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import textwrap
|
||||
import django
|
||||
from django import template
|
||||
from django.utils.html import escape, fix_ampersands, linebreaks
|
||||
from django.utils.html import escape, fix_ampersands
|
||||
from django.template.defaultfilters import linebreaksbr, wordwrap
|
||||
from django.template import resolve_variable
|
||||
try:
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
|
||||
import django.utils.html
|
||||
from django.shortcuts import render_to_response as render, get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.template.loader import render_to_string
|
||||
|
@ -10,11 +9,6 @@ from ietf.ipr.models import IprDetail, SELECT_CHOICES, LICENSE_CHOICES
|
|||
from ietf.ipr.view_sections import section_table
|
||||
from ietf.utils import log
|
||||
|
||||
def linebreaks(value):
|
||||
if value:
|
||||
return django.utils.html.linebreaks(value)
|
||||
else:
|
||||
return value
|
||||
|
||||
def default(request):
|
||||
"""Default page, with links to sub-pages"""
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from django.db import models
|
||||
from ietf.idtracker.models import Acronym, Area
|
||||
import random
|
||||
|
||||
class ImportedMailingList(models.Model):
|
||||
group_acronym = models.ForeignKey(Acronym, null=True)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
from listop import orl, flattenl
|
||||
from log import log
|
||||
from cache_foreign_key import FKAsOneToOne
|
||||
from soup2text import TextSoup, soup2text
|
||||
from draft_search import normalize_draftname
|
||||
|
||||
# See http://docs.python.org/tut/node8.html regarding the use of __all__ and
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
|
||||
import re
|
||||
import textwrap
|
||||
try:
|
||||
from ietf.contrib.BeautifulSoup import Tag, BeautifulSoup, NavigableString
|
||||
except:
|
||||
from BeautifulSoup import Tag, BeautifulSoup, NavigableString
|
||||
|
||||
block_tags = ["[document]", "html", "body", "div", "blockquote", "table", "tr", "p", "pre", "h1", "h2", "h3", "h4", "h5", "h6", "li", "option"]
|
||||
space_tags = ["th", "td"]
|
||||
break_tags = ["br"]
|
||||
ignore_tags = ["head", "script", "style"]
|
||||
pre_tags = ["pre", "option"]
|
||||
entities = [("<", "<"), (">", ">"),
|
||||
(""", '"'), ("'", "'"),
|
||||
(" ", " "),
|
||||
("&", "&"), ] # ampersand last
|
||||
|
||||
def unescape(text):
|
||||
# Unescape character codes (if possible)
|
||||
start = 0
|
||||
while True:
|
||||
try:
|
||||
pos = text.index("&#", start)
|
||||
except ValueError:
|
||||
break
|
||||
match = re.match("&#\d+;", text[pos:])
|
||||
if match:
|
||||
str = match.group()
|
||||
num = int(str[2:-1])
|
||||
if num < 256:
|
||||
text = text[:pos] + chr(num) + text[pos+len(str):]
|
||||
start = pos + 1
|
||||
else:
|
||||
start = pos + len(str)
|
||||
else:
|
||||
start = pos + 2
|
||||
# unescape character entities
|
||||
for entity, char in entities:
|
||||
text = text.replace(entity, char) # replace ampersand last
|
||||
return text
|
||||
|
||||
def para(words, pre, fill):
|
||||
text = "".join(words)
|
||||
text = unescape(text)
|
||||
if not pre:
|
||||
text = text.strip("\n")
|
||||
text = text.lstrip()
|
||||
text = re.sub("[\t\n ]+", " ", text)
|
||||
if fill:
|
||||
text = textwrap.fill(text)
|
||||
return text
|
||||
|
||||
def normalize(str):
|
||||
# Normalize whitespace at the beginning and end of the string
|
||||
str = re.sub("^[ \t]+", " ", str)
|
||||
str = re.sub("[ \t]+$", " ", str)
|
||||
# remove xml PIs and metainformation
|
||||
str = re.sub("<![^>]*>", "", str)
|
||||
str = re.sub("<\?[^>]*\?>", "", str)
|
||||
return str
|
||||
|
||||
def render(node, encoding='latin-1', pre=False, fill=True, clean=True):
|
||||
blocks = []
|
||||
words = []
|
||||
node.pre = pre or node.name in pre_tags
|
||||
node.is_block = node.name in block_tags
|
||||
for child in node:
|
||||
if isinstance(child, NavigableString):
|
||||
str = child.__str__(encoding)
|
||||
if str and not node.pre:
|
||||
str = normalize(str)
|
||||
if str:
|
||||
words.append(str)
|
||||
elif isinstance(child, Tag):
|
||||
if child.name in ignore_tags:
|
||||
pass
|
||||
else:
|
||||
child = render(child, encoding, node.pre, fill, clean)
|
||||
if child.text:
|
||||
if child.is_block:
|
||||
if words :
|
||||
blocks.append(para(words, node.pre, fill)+"\n")
|
||||
words = []
|
||||
blocks.append(child.text+"\n\n")
|
||||
node.is_block = True
|
||||
else:
|
||||
words.append(child.text)
|
||||
if child.text[-1] not in [" ", "\t", "\n"]:
|
||||
if child.name in space_tags:
|
||||
words.append(" ")
|
||||
if child.name in break_tags:
|
||||
words.append("\n")
|
||||
else:
|
||||
raise ValueError("Unexpected node type: '%s'" % child)
|
||||
if words:
|
||||
blocks.append(para(words, node.pre, fill))
|
||||
|
||||
node.text = ''.join(blocks)
|
||||
return node
|
||||
|
||||
class TextSoup(BeautifulSoup):
|
||||
|
||||
def as_text(self, encoding='latin-1', pre=False, fill=True, clean=True):
|
||||
node = render(self, encoding, pre, fill, clean)
|
||||
str = node.text
|
||||
if clean:
|
||||
str = re.sub("[ \t]+", " ", str)
|
||||
str = re.sub("\n\n+", "\n\n", str)
|
||||
return str
|
||||
|
||||
def __str__(self, encoding='latin-1',
|
||||
prettyPrint=False, indentLevel=0):
|
||||
node = render(self, encoding, fill=False)
|
||||
str = node.text
|
||||
str = re.sub("[ \t]+", " ", str)
|
||||
str = re.sub("\n\n+", "\n\n", str)
|
||||
return str
|
||||
|
||||
def soup2text(html, encoding='latin-1', pre=False, fill=True):
|
||||
soup = TextSoup(html)
|
||||
return soup.as_text(encoding, pre, fill)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import urllib2 as urllib
|
||||
for arg in sys.argv[1:]:
|
||||
if arg[:6] in ["http:/", "https:", "ftp://"]:
|
||||
file = urllib.urlopen(arg)
|
||||
else:
|
||||
file = open(arg)
|
||||
html = file.read()
|
||||
file.close()
|
||||
print soup2text(html)
|
|
@ -33,7 +33,7 @@
|
|||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import django
|
||||
from django.db import connection
|
||||
from django.test import TestCase
|
||||
|
|
Loading…
Reference in a new issue