WebHelpers

WebHelpers is a package designed to ease common tasks developers need that are usually done for formatting or displaying data in templates.

Helpers available by module:

Date

webhelpers.date.distance_of_time_in_words(from_time, to_time=0, granularity='second', round=False)

Return the absolute time-distance string for two datetime objects, ints or any combination of which you can dream

If times are integers, they are interpreted as seconds from now

granularity dictates where the string calculation is stopped. If set to seconds (default) you will receive the full string. If another accuracy is supplied you will be provided with an approximation stopping at the granularity supplied. Available parameter values are:

‘century’, ‘decade’, ‘year’, ‘month’, ‘day’, ‘hour’, ‘minute’, ‘second’

Setting round to true will check the granularity finer than the set granularity and if the value is greater than 50% of it’s range the value at granularity will be increased by 1

Examples:

>>> distance_of_time_in_words(86399, round=True, granularity='day')
'1 day'
>>> distance_of_time_in_words(86399, granularity='day')
'less than 1 day'
>>> distance_of_time_in_words(86399)
'23 hours, 59 minutes and 59 seconds'
>>> distance_of_time_in_words(datetime(2008,3,21, 16,34),
... datetime(2008,2,6,9,45))
'1 month, 15 days, 6 hours and 49 minutes'
>>> distance_of_time_in_words(datetime(2008,3,21, 16,34), 
... datetime(2008,2,6,9,45), granularity='decade')
'less than 1 decade'
>>> distance_of_time_in_words(datetime(2008,3,21, 16,34), 
... datetime(2008,2,6,9,45), granularity='second')
'1 month, 15 days, 6 hours and 49 minutes'
webhelpers.date.time_ago_in_words(from_time, granularity='second', round=False)

Return approximate-time-distance string for from_time till now.

See distance_of_time_in_words – same here, but to_time is fixed to datetime.now().

FeedGenerator

The feed generator is intended for use in controllers, and generates an output stream. Currently the following feeds can be created by imported the appropriate class:

  • RssFeed
  • RssUserland091Feed
  • Rss201rev2Feed
  • Atom1Feed

All of these format specific Feed generators inherit from the SyndicationFeed() class.

Example controller method:

import logging

from pylons import request, response, session
from pylons import tmpl_context as c
from pylons.controllers.util import abort, redirect_to, url_for
from webhelpers.feedgenerator import Atom1Feed

from helloworld.lib.base import BaseController, render

log = logging.getLogger(__name__)

class CommentsController(BaseController):

    def index(self):
        feed = Atom1Feed(
            title=u"An excellent Sample Feed",
            link=url_for(),
            description=u"A sample feed, showing how to make and add entries",
            language=u"en",
        )
        feed.add_item(title="Sample post",
                      link=u"http://hellosite.com/posts/sample",
                      description="Testing.")
        response.content_type = 'application/atom+xml'
        return feed.writeString('utf-8')
class webhelpers.feedgenerator.SyndicationFeed(title, link, description, language=None, author_email=None, author_name=None, author_link=None, subtitle=None, categories=None, feed_url=None, feed_copyright=None, feed_guid=None, ttl=None)

Base class for all syndication feeds. Subclasses should provide write()

__init__(title, link, description, language=None, author_email=None, author_name=None, author_link=None, subtitle=None, categories=None, feed_url=None, feed_copyright=None, feed_guid=None, ttl=None)
add_item(title, link, description, author_email=None, author_name=None, author_link=None, pubdate=None, comments=None, unique_id=None, enclosure=None, categories=(), item_copyright=None, ttl=None)
Adds an item to the feed. All args are expected to be Python Unicode objects except pubdate, which is a datetime.datetime object, and enclosure, which is an instance of the Enclosure class.
latest_post_date()

Returns the latest item’s pubdate.

If none of them have a pubdate, this returns the current date/time.

write(outfile, encoding)
Outputs the feed in the given encoding to outfile, which is a file-like object. Subclasses should override this.
writeString(encoding)
Returns the feed in the given encoding as a string.

Converters

Functions that convert from text markup languages to HTML

webhelpers.html.converters.markdown(text, **kwargs)

Format the text to HTML with MarkDown formatting.

This function uses the Python MarkDown library which is included with WebHelpers. It does not include extensions due to circular import issues. If you need the footnotes or RSS extensions, use the full Markdown package instead.

IMPORTANT: If your source text is untrusted and may contain malicious HTML markup, pass safe_mode="escape" to escape it, safe_mode="replace" to replace it with a scolding message, or safe_mode="remove" to strip it.

There is at least one other Markdown package for Python. python-markdown2 (http://code.google.com/p/python-markdown2/), which claims to be faster and to handle edge cases better. WebHelpers is sticking to the original Python Markdown for now for backward compatibility and because nobody has complained about the speed.

webhelpers.html.converters.textilize(text, sanitize=False)

Format the text to HTML with Textile formatting.

This function uses the PyTextile library which is included with WebHelpers.

Additionally, the output can be sanitized which will fix tags like <img />, <br /> and <hr /> for proper XHTML output.

Secure Forms

Secure Form Tag Helpers – For prevention of Cross-site request forgery (CSRF) attacks.

Generates form tags that include client-specific authorization tokens to be verified by the destined web app.

Authorization tokens are stored in the client’s session. The web app can then verify the request’s submitted authorization token with the value in the client’s session.

This ensures the request came from the originating page. See http://en.wikipedia.org/wiki/Cross-site_request_forgery for more information.

Pylons provides an authenticate_form decorator that does this verfication on the behalf of controllers.

These helpers depend on Pylons’ session object. Most of them can be easily ported to another framework by changing the API calls.

The helpers are implemented in such a way that it should be easy to create your own helpers if you are using helpers for AJAX calls.

authentication_token() returns the current authentication token, creating one and storing it in the session if it doesn’t already exist.

auth_token_hidden_field() creates a hidden field (wrapped in an invisible div; I don’t know if this is necessary, but the old WebHelpers had it like this) containing the authentication token.

secure_form() is form() plus auth_token_hidden_field().

webhelpers.html.secure_form.secure_form(url, method='POST', multipart=False, **attrs)

Start a form tag that points the action to an url. This form tag will also include the hidden field containing the auth token.

The url options should be given either as a string, or as a url() function. The method for the form defaults to POST.

Options:

multipart
If set to True, the enctype is set to “multipart/form-data”.
method
The method to use when submitting the form, usually either “GET” or “POST”. If “PUT”, “DELETE”, or another verb is used, a hidden input with name _method is added to simulate the verb over POST.

Tags

Helpers producing simple HTML tags

Most helpers have an \*\*attrs argument to specify additional HTML attributes. A trailing underscore in the name will be deleted; this is especially important for attributes that match Python keywords; e.g., class_. Some helpers handle certain keywords specially; these are noted in the helpers’ docstrings.

Form Tags

webhelpers.html.tags.checkbox(name, value='1', checked=False, label=None, id=None, **attrs)

Create a check box.

Arguments: name – the widget’s name.

value – the value to return to the application if the box is checked.

checked – true if the box should be initially checked.

label – a text label to display to the right of the box.

id is the HTML ID attribute, and should be passed as a keyword argument. By default the ID is the same as the name filtered through _make_safe_id_component(). Pass the empty string (“”) to suppress the ID attribute entirely.

d

The following HTML attributes may be set by keyword argument:

  • disabled - If true, checkbox will be grayed out.
  • readonly - If true, the user will not be able to modify the checkbox.

To arrange multiple checkboxes in a group, see webhelpers.containers.distribute().

Example:

>>> checkbox("hi")
literal(u'<input id="hi" name="hi" type="checkbox" value="1" />')
webhelpers.html.tags.end_form()

Output “</form>”.

Example:

>>> end_form()
literal(u'</form>')
webhelpers.html.tags.file(name, value=None, id=None, **attrs)

Create a file upload field.

If you are using file uploads then you will also need to set the multipart option for the form.

Example:

>>> file('myfile')
literal(u'<input id="myfile" name="myfile" type="file" />')
webhelpers.html.tags.form(url, method='post', multipart=False, **attrs)

An open tag for a form that will submit to url.

You must close the form yourself by calling end_form() or outputting </form>.

Options:

multipart
If set to True, the enctype is set to “multipart/form-data”. You must set it to true when uploading files, or the browser will submit the filename rather than the file.
method
The method to use when submitting the form, usually either “GET” or “POST”. If “PUT”, “DELETE”, or another verb is used, a hidden input with name _method is added to simulate the verb over POST.

Examples:

>>> form("/submit")
literal(u'<form action="/submit" method="post">')
>>> form("/submit", method="get")
literal(u'<form action="/submit" method="get">')
>>> form("/submit", method="put")
literal(u'<form action="/submit" method="post"><input name="_method" type="hidden" value="put" />')
>>> form("/submit", "post", multipart=True) 
literal(u'<form action="/submit" enctype="multipart/form-data" method="post">')
webhelpers.html.tags.hidden(name, value=None, **attrs)
Create a hidden field.
webhelpers.html.tags.password(name, value=None, id=None, **attrs)

Create a password field.

Takes the same options as text().

webhelpers.html.tags.radio(name, value, checked=False, label=None, **attrs)

Create a radio button.

Arguments: name – the field’s name.

value – the value returned to the application if the button is pressed.

checked – true if the button should be initially pressed.

label – a text label to display to the right of the button.

The id of the radio button will be set to the name + ‘_’ + value to ensure its uniqueness. An id keyword arg overrides this. (Note that this behavior is unique to the radio() helper.)

To arrange multiple radio buttons in a group, see webhelpers.containers.distribute().

webhelpers.html.tags.select(name, selected_values, options, id=None, **attrs)

Create a dropdown selection box.

  • name – the name of this control.
  • selected_values – a string or list of strings or integers giving the value(s) that should be preselected.
  • options – an Options object or iterable of (value, label) pairs. The label will be shown on the form; the option will be returned to the application if that option is chosen. If you pass a string or int instead of a 2-tuple, it will be used for both the value and the label.

id is the HTML ID attribute, and should be passed as a keyword argument. By default the ID is the same as the name. filtered through _make_safe_id_component(). Pass the empty string (“”) to suppress the ID attribute entirely.

CAUTION: the old rails helper options_for_select had the label first. The order was reversed because most real-life collections have the value first, including dicts of the form {value: label}. For those dicts you can simply pass D.items() as this argument.

HINT: You can sort options alphabetically by label via: sorted(my_options, key=lambda x: x[1])

The following options may only be keyword arguments:

  • multiple – if true, this control will allow multiple

    selections.

  • prompt – if specified, an extra option will be prepended to the list: (“”, prompt). This is intended for those “Please choose ...” pseudo-options. Its value is “”, equivalent to not making a selection.

Any other keyword args will become HTML attributes for the <select>.

Examples (call, result):

>>> select("currency", "$", [["$", "Dollar"], ["DKK", "Kroner"]])
literal(u'<select id="currency" name="currency">\n<option selected="selected" value="$">Dollar</option>\n<option value="DKK">Kroner</option>\n</select>')
>>> select("cc", "MasterCard", [ "VISA", "MasterCard" ], id="cc", class_="blue")
literal(u'<select class="blue" id="cc" name="cc">\n<option value="VISA">VISA</option>\n<option selected="selected" value="MasterCard">MasterCard</option>\n</select>')
>>> select("cc", ["VISA", "Discover"], [ "VISA", "MasterCard", "Discover" ])
literal(u'<select id="cc" name="cc">\n<option selected="selected" value="VISA">VISA</option>\n<option value="MasterCard">MasterCard</option>\n<option selected="selected" value="Discover">Discover</option>\n</select>')
>>> select("currency", None, [["$", "Dollar"], ["DKK", "Kroner"]], prompt="Please choose ...")
literal(u'<select id="currency" name="currency">\n<option selected="selected" value="">Please choose ...</option>\n<option value="$">Dollar</option>\n<option value="DKK">Kroner</option>\n</select>')
>>> select("privacy", 3L, [(1, "Private"), (2, "Semi-public"), (3, "Public")])
literal(u'<select id="privacy" name="privacy">\n<option value="1">Private</option>\n<option value="2">Semi-public</option>\n<option selected="selected" value="3">Public</option>\n</select>')
webhelpers.html.tags.submit(name, value, id=None, **attrs)
Create a submit button with the text value as the caption.
webhelpers.html.tags.text(name, value=None, id=None, **attrs)

Create a standard text field.

value is a string, the content of the text field.

id is the HTML ID attribute, and should be passed as a keyword argument. By default the ID is the same as the name filtered through _make_safe_id_component(). Pass the empty string (“”) to suppress the ID attribute entirely.

Options:

  • disabled - If set to True, the user will not be able to use

    this input.

  • size - The number of visible characters that will fit in the

    input.

  • maxlength - The maximum number of characters that the browser

    will allow the user to enter.

The remaining keyword args will be standard HTML attributes for the tag.

webhelpers.html.tags.textarea(name, content='', id=None, **attrs)

Create a text input area.

Example:

>>> textarea("body", "", cols=25, rows=10)
literal(u'<textarea cols="25" id="body" name="body" rows="10"></textarea>')
class webhelpers.html.tags.ModelTags(record, use_keys=False, date_format='%m/%d/%Y', id_format=None)

A nice way to build a form for a database record.

ModelTags allows you to build a create/update form easily. (This is the C and U in CRUD.) The constructor takes a database record, which can be a SQLAlchemy mapped class, or any object with attributes or keys for the field values. Its methods shadow the the form field helpers, but it automatically fills in the value attribute based on the current value in the record. (It also knows about the ‘checked’ and ‘selected’ attributes for certain tags.)

You can also use the same form to input a new record. Pass None or "" instead of a record, and it will set all the current values to a default value, which is either the default keyword arg to the method, or “” if not specified.

(Hint: in Pylons you can put mt = ModelTags(c.record) in your template, and then if the record doesn’t exist you can either set c.record = None or not set it at all. That’s because nonexistent c attributes resolve to “” unless you’ve set config["pylons.strict_c"] = True. However, having a c attribute that’s sometimes set and sometimes not is arguably bad programming style.)

__init__(record, use_keys=False, date_format='%m/%d/%Y', id_format=None)

Create a ModelTags object.

record is the database record to lookup values in. It may be any object with attributes or keys, including a SQLAlchemy mapped instance. It may also be None or "" to indicate that a new record is being created. (The class attribute undefined_values tells which values indicate a new record.)

If use_keys is true, values will be looked up by key. If false (default), values will be looked up by attribute.

date_format is a strftime-compatible string used by the .date method. The default is American format (MM/DD/YYYY), which is most often seen in text fields paired with popup calendars. European format (DD/MM/YYYY) is “%d/%m/%Y”. ISO format (YYYY-MM-DD) is “%Y-%m-%d”.

id_format is a formatting-operator format for the HTML ‘id’ attribute. It should contain one “%s” where the tag’s name will be embedded.

checkbox(name, value='1', label=None, **kw)

Build a checkbox field.

The box will be initially checked if the value of the corresponding database field is true.

The submitted form value will be “1” if the box was checked. If the box is unchecked, no value will be submitted. (This is a downside of the standard checkbox tag.)

To display multiple checkboxes in a group, see webhelper.containers.distribute().

date(name, **kw)

Same as text but format a date value into a date string.

The value can be a datetime.date, datetime.datetime, None, or “”. The former two are converted to a string using the date format passed to the constructor. The latter two are converted to “”.

If there’s no database record, consult keyword arg default. It it’s the string “today”, use todays’s date. Otherwise it can be any of the values allowed above. If no default is specified, the text field is initialized to “”.

Hint: you may wish to attach a Javascript calendar to the field.

file(name, **kw)

Build a file upload field.

User agents may or may not respect the contents of the ‘value’ attribute.

hidden(name, **kw)
Build a hidden HTML field.
password(name, **kw)

Build a password field.

This is the same as a text box but the value will not be shown on the screen as the user types.

radio(name, checked_value, label=None, **kw)

Build a radio button.

The radio button will initially be selected if the database value equals checked_value. On form submission the value will be checked_value if the button was selected, or "" otherwise.

The control’s ‘id’ attribute will be modified as follows:

  1. If not specified but an ‘id_format’ was given to the constructor, generate an ID based on the format.
  2. If an ID was passed in or was generated by step (1), append an underscore and the checked value. Before appending the checked value, lowercase it, change any spaces to "_", and remove any non-alphanumeric characters except underscores and hyphens.
  3. If no ID was passed or generated by step (1), the radio button will not have an ‘id’ attribute.

To display multiple radio buttons in a group, see webhelper.containers.distribute().

select(name, options, **kw)

Build a dropdown select box or list box.

See the select() function for the meaning of the arguments.

If the corresponding database value is not a list or tuple, it’s wrapped in a one-element list. But if it’s “” or None, an empty list is substituted. This is to accommodate multiselect lists, which may have multiple values selected.

text(name, **kw)
Build a text box.
textarea(name, **kw)
Build a rectangular text area.

Other Tags

webhelpers.html.tags.image(url, alt, width=None, height=None, **attrs)

Return an image tag for the specified source.

url
The URL of the image. (This must be the exact URL desired. A previous version of this helper added magic prefixes; this is no longer the case.)
alt
The img’s alt tag. Non-graphical browsers and screen readers will output this instead of the image. If the image is pure decoration and uninteresting to non-graphical users, pass “”. To omit the alt tag completely, pass None.
width
The width of the image, default is not included
height
The height of the image, default is not included

Examples:

>>> image('/images/rss.png', 'rss syndication')
literal(u'<img alt="rss syndication" src="/images/rss.png" />')

>>> image('/images/xml.png', "")
literal(u'<img alt="" src="/images/xml.png" />')

>>> image("/images/icon.png", height=16, width=10, alt="Edit Entry")
literal(u'<img alt="Edit Entry" height="16" src="/images/icon.png" width="10" />')

>>> image("/icons/icon.gif", alt="Icon", width=16, height=16)
literal(u'<img alt="Icon" height="16" src="/icons/icon.gif" width="16" />')

>>> image("/icons/icon.gif", None, width=16)
literal(u'<img alt="" src="/icons/icon.gif" width="16" />')

Head Tags

Return a link tag allowing auto-detecting of RSS or ATOM feed.

The auto-detection of feed for the current page is only for browsers and news readers that support it.

url
The URL of the feed. (This should be the exact URLs desired. A previous version of this helper added magic prefixes; this is no longer the case.)
feed_type
The type of feed. Specifying ‘rss’ or ‘atom’ automatically translates to a type of ‘application/rss+xml’ or ‘application/atom+xml’, respectively. Otherwise the type is used as specified. Defaults to ‘rss’.

Examples:

>>> auto_discovery_link('http://feed.com/feed.xml')
literal(u'<link href="http://feed.com/feed.xml" rel="alternate" title="RSS" type="application/rss+xml" />')

>>> auto_discovery_link('http://feed.com/feed.xml', feed_type='atom')
literal(u'<link href="http://feed.com/feed.xml" rel="alternate" title="ATOM" type="application/atom+xml" />')

>>> auto_discovery_link('app.rss', feed_type='atom', title='atom feed')
literal(u'<link href="app.rss" rel="alternate" title="atom feed" type="application/atom+xml" />')

>>> auto_discovery_link('/app.html', feed_type='text/html')
literal(u'<link href="/app.html" rel="alternate" title="" type="text/html" />')

Return script include tags for the specified javascript URLs.

urls should be the exact URLs desired. A previous version of this helper added magic prefixes; this is no longer the case.

Specify the keyword argument defer=True to enable the script defer attribute.

Examples:

>>> print javascript_link('/javascripts/prototype.js', '/other-javascripts/util.js')
<script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/other-javascripts/util.js" type="text/javascript"></script>

>>> print javascript_link('/app.js', '/test/test.1.js')
<script src="/app.js" type="text/javascript"></script>
<script src="/test/test.1.js" type="text/javascript"></script>

Return CSS link tags for the specified stylesheet URLs.

urls should be the exact URLs desired. A previous version of this helper added magic prefixes; this is no longer the case.

Examples:

>>> stylesheet_link('/stylesheets/style.css')
literal(u'<link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />')

>>> stylesheet_link('/stylesheets/dir/file.css', media='all')
literal(u'<link href="/stylesheets/dir/file.css" media="all" rel="stylesheet" type="text/css" />')

Utility

webhelpers.html.tags.convert_boolean_attrs(attrs, bool_attrs)

Convert boolean values into proper HTML attributes.

attrs is a dict of HTML attributes, which will be modified in place.

bool_attrs is a list of attribute names.

For every element in bool_attrs, I look for a corresponding key in attrs. If its value is true, I change the value to match the key. For example, I convert selected=True into selected="selected". If the value is false, I delete the key.

Tools

Powerful HTML helpers that produce more than just simple tags.

Turn all urls and email addresses into clickable links.

link
Used to determine what to link. Options are “all”, “email_addresses”, or “urls”

Example:

>>> auto_link("Go to http://www.planetpython.com and say hello to guido@python.org")
literal(u'Go to <a href="http://www.planetpython.com">http://www.planetpython.com</a> and say hello to <a href="mailto:guido@python.org">guido@python.org</a>')
webhelpers.html.tools.button_to(name, url='', **html_options)

Generate a form containing a sole button that submits to url.

Use this method instead of link_to for actions that do not have the safe HTTP GET semantics implied by using a hypertext link.

The parameters are the same as for link_to. Any html_options that you pass will be applied to the inner input element. In particular, pass

disabled = True/False

as part of html_options to control whether the button is disabled. The generated form element is given the class ‘button-to’, to which you can attach CSS styles for display purposes.

The submit button itself will be displayed as an image if you provide both type and src as followed:

type=’image’, src=’icon_delete.gif’

The src path should be the exact URL desired. A previous version of this helper added magical prefixes but this is no longer the case.

Example 1:

# inside of controller for "feeds"
>> button_to("Edit", url(action='edit', id=3))
<form method="POST" action="/feeds/edit/3" class="button-to">
<div><input value="Edit" type="submit" /></div>
</form>

Example 2:

>> button_to("Destroy", url(action='destroy', id=3), 
.. method='DELETE')
<form method="POST" action="/feeds/destroy/3" 
 class="button-to">
<div>
    <input type="hidden" name="_method" value="DELETE" />
    <input value="Destroy" type="submit" />
</div>
</form>

Example 3:

# Button as an image.
>> button_to("Edit", url(action='edit', id=3), type='image', 
.. src='icon_delete.gif')
<form method="POST" action="/feeds/edit/3" class="button-to">
<div><input alt="Edit" src="/images/icon_delete.gif"
 type="image" value="Edit" /></div>
</form>

Note

This method generates HTML code that represents a form. Forms are “block” content, which means that you should not try to insert them into your HTML where only inline content is expected. For example, you can legally insert a form inside of a div or td element or in between p elements, but not in the middle of a run of text, nor can you place a form within another form. (Bottom line: Always validate your HTML before going public.)

webhelpers.html.tools.highlight(text, phrase, highlighter='<strong class="highlight">\1</strong>')

Highlight the phrase where it is found in the text.

The highlighted phrase will be surrounded by the highlighter, by default:

<strong class="highlight">I'm a highlight phrase</strong>
highlighter
Defines the highlighting phrase. This argument should be a single-quoted string with \1 where the phrase is supposed to be inserted.

Note: The phrase is sanitized to include only letters, digits, and spaces before use.

Example:

>>> highlight('You searched for: Pylons', 'Pylons')
'You searched for: <strong class="highlight">Pylons</strong>'
webhelpers.html.tools.mail_to(email_address, name=None, cc=None, bcc=None, subject=None, body=None, replace_at=None, replace_dot=None, encode=None, **html_options)

Create a link tag for starting an email to the specified email_address.

This email_address is also used as the name of the link unless name is specified. Additional HTML options, such as class or id, can be passed in the html_options hash.

You can also make it difficult for spiders to harvest email address by obfuscating them.

Examples:

>>> mail_to("me@domain.com", "My email", encode = "javascript")
literal(u'<script type="text/javascript">\n//<![CDATA[\neval(unescape(\'%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b\'))\n//]]>\n</script>')

>>> mail_to("me@domain.com", "My email", encode = "hex")
literal(u'<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>')

You can also specify the cc address, bcc address, subject, and body parts of the message header to create a complex e-mail using the corresponding cc, bcc, subject, and body keyword arguments. Each of these options are URI escaped and then appended to the email_address before being output. Be aware that javascript keywords will not be escaped and may break this feature when encoding with javascript.

Examples:

>>> mail_to("me@domain.com", "My email", cc="ccaddress@domain.com", bcc="bccaddress@domain.com", subject="This is an example email", body= "This is the body of the message.")
literal(u'<a href="mailto:me@domain.com?cc=ccaddress%40domain.com&amp;bcc=bccaddress%40domain.com&amp;subject=This%20is%20an%20example%20email&amp;body=This%20is%20the%20body%20of%20the%20message.">My email</a>')

Strip link tags from text leaving just the link label.

Example:

>>> strip_links('<a href="something">else</a>')
'else'

MIMEType Helper

The MIMEType helper assists in delivering appropriate content types for a single action in a controller, based on several requirements:

  1. Does the URL end in a specific extension? (.html, .xml, etc.)
  2. Can the client accept HTML?
  3. What Accept headers did the client send?

If the URL ends in an extension, the mime-type associated with that is given the highest preference. Since some browsers fail to properly set their Accept headers to indicate they should be serving HTML, the next check looks to see if its at least in the list. This way those browsers will still get the HTML they are expecting.

Finally, if the client didn’t include an extension, and doesn’t have HTML in the list of Accept headers, than the desired mime-type is returned if the server can send it.

class webhelpers.mimehelper.MIMETypes(environ)

MIMETypes registration mapping

The MIMETypes object class provides a single point to hold onto all the registered mimetypes, and their association extensions. It’s used by the mimetypes function to determine the appropriate content type to return to a client.

classmethod add_alias(alias, mimetype)

Creates a MIMEType alias to a full mimetype

These aliases may not include /’s. Examples include html->text/html, xml->application/xml.

classmethod init()

Loads a default mapping of extensions and mimetypes

These are suitable for most web applications by default. Additional types can be added with the using the mimetypes module.

mimetype(content_type)

Check the PATH_INFO of the current request and clients HTTP Accept to attempt to use the appropriate mime-type

If a content-type is matched, the appropriate response content type is set as well.

This works best with URLs that end in extensions that differentiate content-type. Examples: http://example.com/example, http://example.com/example.xml, http://example.com/example.csv

Since browsers generally allow for any content-type, but should be sent HTML when possible, the html mimetype check should always come first, as shown in the example below.

Example:

# some code likely in environment.py
MIMETypes.init()
MIMETypes.add_alias('html', 'text/html')
MIMETypes.add_alias('xml', 'application/xml')
MIMETypes.add_alias('csv', 'text/csv')

# code in a controller
def somaction(self):
    # prepare a bunch of data
    # ......
    
    # prepare MIMETypes object
    m = MIMETypes(request.environ)
    
    if m.mimetype('html'):
        return render('/some/template.html')
    elif m.mimetype('atom'):
        return render('/some/xml_template.xml')
    elif m.mimetype('csv'):
        # write the data to a csv file
        return csvfile
    else:
        abort(404)

Number

Number formatting and calculation helpers.

webhelpers.number.format_number(n, thousands=', ', decimal='.')

Format a number with a thousands separator and decimal delimeter.

n may be an int, long, float, or numeric string. thousands is a separator to put after each thousand. decimal is the delimiter to put before the fractional portion if any.

The default style has a thousands comma and decimal point per American usage:

>>> format_number(1234567.89)
'1,234,567.89'
>>> format_number(123456)
'123,456'
>>> format_number(-123)
'-123'

Various European and international styles are also possible:

>>> format_number(1234567.89, " ")
'1 234 567.89'
>>> format_number(1234567.89, " ", ",")
'1 234 567,89'
>>> format_number(1234567.89, ".", ",")
'1.234.567,89'
webhelpers.number.mean(r)

Return the mean of a sequence of numbers.

The mean is the average of all the numbers.

>>> mean([5, 10])
7.5
webhelpers.number.median(r)

Return the median of an iterable of numbers.

The median is the point at which half the numbers are lower than it and half the numbers are higher. This gives a better sense of the majority level than the mean (average) does, because the mean can be skewed by a few extreme numbers at either end. For instance, say you want to calculate the typical household income in a community and you’ve sampled four households:

>>> incomes = [18000]       # Fast food crew
>>> incomes.append(24000)   # Janitor
>>> incomes.append(32000)   # Journeyman
>>> incomes.append(44000)   # Experienced journeyman
>>> incomes.append(67000)   # Manager
>>> incomes.append(9999999) # Bill Gates
>>> median(incomes)
49500.0
>>> mean(incomes)
1697499.8333333333

The median here is somewhat close to the majority of incomes, while the mean is far from anybody’s income.

[20 000, 40 000, 60 000, 9 999 999]

The median would be around 50 000, which is close to what the majority of respondents make. The average would be in the millions, which is far from what any of the respondents make.

This implementation makes a temporary list of all numbers in memory.

webhelpers.number.percent_of(part, whole)

What percent of whole is part?

>>> percent_of(5, 100)
5.0
>>> percent_of(13, 26)
50.0
webhelpers.number.standard_deviation(r, sample=True)

Standard deviation, from the Python Cookbook Population mode contributed by Lorenzo Catucci.

Standard deviation shows the variability within a sequence of numbers. A small standard deviation shows the numbers are close to the same. A large standard deviation shows they are widely different. In fact it shows how far the numbers tend to deviate from the average. This can be used to detect whether the average has been skewed by a few extremely high or extremely low values.

By default the helper computes the unbiased estimate for the population standard deviation, by applying an unbiasing factor of sqrt(N/(N-1)).

If you’d rather have the function compute the population standard deviation, pass sample=False.

The following examples are taken from Wikipedia. http://en.wikipedia.org/wiki/Standard_deviation

>>> standard_deviation([0, 0, 14, 14]) # doctest: +ELLIPSIS
8.082903768654761...
>>> standard_deviation([0, 6, 8, 14]) # doctest: +ELLIPSIS
5.773502691896258...
>>> standard_deviation([6, 6, 8, 8])
1.1547005383792515
>>> standard_deviation([0, 0, 14, 14], sample=False)
7.0
>>> standard_deviation([0, 6, 8, 14], sample=False)
5.0
>>> standard_deviation([6, 6, 8, 8], sample=False)
1.0

(The results reported in Wikipedia are those expected for whole population statistics and therefore are equal to the ones we get by setting sample=False in the later tests.)

# Fictitious average monthly temperatures in Southern California.
#                       Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
>>> standard_deviation([70, 70, 70, 75, 80, 85, 90, 95, 90, 80, 75, 70]) # doctest: +ELLIPSIS
9.003366373785...
>>> standard_deviation([70, 70, 70, 75, 80, 85, 90, 95, 90, 80, 75, 70], sample=False) # doctest: +ELLIPSIS
8.620067027323...

# Fictitious average monthly temperatures in Montana.
#                       Jan  Feb  Mar Apr May Jun Jul  Aug Sep Oct Nov Dec
>>> standard_deviation([-32, -10, 20, 30, 60, 90, 100, 80, 60, 30, 10, -32]) # doctest: +ELLIPSIS
45.1378360405574...
>>> standard_deviation([-32, -10, 20, 30, 60, 90, 100, 80, 60, 30, 10, -32], sample=False) # doctest: +ELLIPSIS
43.2161878106906...

Most natural and random phenomena follow the normal distribution (aka the bell curve), which says that most values are close to average but a few are extreme. E.g., most people are close to 5‘9” tall but a few are very tall or very short. If the data does follow the bell curve, 68% of the values will be within 1 standard deviation (stdev) of the average, and 95% will be within 2 standard deviations. So a university professor grading exams on a curve might give a “C” (mediocre) grade to students within 1 stdev of the average score, “B” (better than average) to those within 2 stdevs above, and “A” (perfect) to the 0.25% higher than 2 stdevs. Those between 1 and 2 stdevs below get a “D” (poor), and those below 2 stdevs... we won’t talk about them.

class webhelpers.number.Stats

A container for data and statistics.

This class extends SimpleStats by calculating additional statistics, and by storing all data seen. All values must be numeric (int, long, and/or float), and you must call .finish() to generate the additional statistics. That’s because the statistics here cannot be calculated incrementally, but only after all data is known.

>>> stats = Stats()
>>> stats.extend([5, 10, 10])
>>> stats.count
3
>>> stats.finish()
>>> stats.mean # doctest: +ELLIPSIS
8.33333333333333...
>>> stats.median
10
>>> stats.standard_deviation
2.8867513459481287

All data is stored in a list and a set for later use:

>>> stats.list
[5, 10, 10]

>>  stats.set
set([5, 10])

(The double prompt “>>” is used to hide the example from doctest.)

The stat attributes are None until you call .finish(). It’s permissible – though not recommended – to add data after calling .finish() and then call .finish() again. This recalculates the stats over the entire data set.

The SimpleStats hook methods are available for subclasses, and additionally the ._finish_stats method.

class webhelpers.number.SimpleStats(numeric=False)

Calculate a few simple stats on data.

This class calculates the minimum, maximum, and count of all the values given to it. The values are not saved in the object. Usage:

>>> stats = SimpleStats()
>>> stats(2)               # Add one data value.
>>> stats.extend([6, 4])   # Add several data values at once.  

The statistics are available as instance attributes:

>>> stats.count
3
>>> stats.min
2
>>> stats.max
6

Non-numeric data is also allowed:

>>> stats2 = SimpleStats()
>>> stats2("foo")
>>> stats2("bar")
>>> stats2.count
2
>>> stats2.min
'bar'
>>> stats2.max
'foo'

If the numeric constructor arg is true, only int, long, and float values will be accepted. This flag is intended to enable additional numeric statistics, although none are currently implemented.

.min and .max are None until the first data value is registered.

Subclasses can override ._init_stats and ._update_stats to add additional statistics.

Misc

Helpers that are neither text, numeric, container, or date.

webhelpers.misc.all(seq, pred=None)

Is pred(elm) true for all elements?

With the default predicate, this is the same as Python 2.5’s all() function; i.e., it returns true if all elements are true.

>>> all(["A", "B"])
True
>>> all(["A", ""])
False
>>> all(["", ""])
False
>>> all(["A", "B", "C"], lambda x: x <= "C")
True
>>> all(["A", "B", "C"], lambda x: x < "C")
False

From recipe in itertools docs.

webhelpers.misc.any(seq, pred=None)

Is pred(elm) is true for any element?

With the default predicate, this is the same as Python 2.5’s any() function; i.e., it returns true if any element is true.

>>> any(["A", "B"])
True
>>> any(["A", ""])
True
>>> any(["", ""])
False
>>> any(["A", "B", "C"], lambda x: x <= "C")
True
>>> any(["A", "B", "C"], lambda x: x < "C")
True

From recipe in itertools docs.

webhelpers.misc.no(seq, pred=None)

Is pred(elm) false for all elements?

With the default predicate, this returns true if all elements are false.

>>> no(["A", "B"])
False
>>> no(["A", ""])
False
>>> no(["", ""])
True
>>> no(["A", "B", "C"], lambda x: x <= "C")
False
>>> no(["X", "Y", "Z"], lambda x: x <="C")
True

From recipe in itertools docs.

webhelpers.misc.count_true(seq, pred=<function <lambda> at 0xe7b7410>)

How many elements is pred(elm) true for?

With the default predicate, this counts the number of true elements.

>>> count_true([1, 2, 0, "A", ""])
3
>>> count_true([1, "A", 2], lambda x: isinstance(x, int))
2

This is equivalent to the itertools.quantify recipe, which I couldn’t get to work.

webhelpers.misc.convert_or_none(value, type_)

Return the value converted to the type, or None if error. type_ may be a Python type or any function taking one argument.

>>> print convert_or_none("5", int)
5
>>> print convert_or_none("A", int)
None

Pylons-specific

class webhelpers.pylonslib.Flash(session_key='flash')

Accumulate a list of messages to show at the next page request.

This class is useful when you want to redirect to another page and also show a status message on that page, such as “Changes saved” or “No previous search found; returning to home page”.

THIS IMPLEMENTATION DEPENDS ON PYLONS. However, it can easily be adapted for another web framework.

Normally you instantiate a Flash object in myapp/lib/helpers.py:

from webhelpers.pylonslib import Flash as _Flash
flash = _Flash()

The helpers module is then imported into your controllers and templates as h. Whenever you want to set a message, do this:

h.flash("Record deleted.")

You can set additional messages too:

h.flash("Hope you didn't need it.")

Now make a place in your site template for the messages. In Mako you might do:

<% messages = h.flash.pop_messages() %>
% if messages:
<ul id="flash-messages">
    % for message in messages:
    <li>${message}</li>
    % endfor
</ul>
% endif

You can style this to look however you want:

ul#flash-messages {
    color: red;
    background-color: #FFFFCC;
    font-size: larger;
    font-style: italic;
    margin-left: 40px;
    padding: 4px;
    list-style: none;
    }
__init__(session_key='flash')
__call__(message)

Text

Functions that output text (not HTML).

Helpers for filtering, formatting, and transforming strings.

webhelpers.text.chop_at(s, sub, inclusive=False)

Truncate string s at the first occurence of sub.

If inclusive is true, truncate just after sub rather than at it.

>>> chop_at("plutocratic brats", "rat")
'plutoc'
>>> chop_at("plutocratic brats", "rat", True)
'plutocrat'
webhelpers.text.excerpt(text, phrase, radius=100, excerpt_string='...')

Extract an excerpt from the text, or ‘’ if the phrase isn’t found.

phrase
Phrase to excerpt from text
radius
How many surrounding characters to include
excerpt_string
Characters surrounding entire excerpt

Example:

>>> excerpt("hello my world", "my", 3)
'...lo my wo...'
webhelpers.text.lchop(s, sub)

Chop sub off the front of s if present.

>>> lchop("##This is a comment.##", "##")
'This is a comment.##'
webhelpers.text.plural(n, singular, plural, with_number=True)

Return the singular or plural form of a word, according to the number.

Usage: >>> plural(2, “ox”, “oxen”) ‘2 oxen’ >>> plural(2, “ox”, “oxen”, False) ‘oxen’

webhelpers.text.rchop(s, sub)

Chop sub off the end of s if present.

>>> rchop("##This is a comment.##", "##")
'##This is a comment.'
webhelpers.text.strip_leading_whitespace(s)

Strip the leading whitespace in all lines in s.

This deletes all leading whitespace. textwrap.dedent deletes only the whitespace common to all lines.

webhelpers.text.truncate(text, length=30, indicator='...', whole_word=False)

Truncate text with replacement characters.

length
The maximum length of text before replacement
indicator
If text exceeds the length, this string will replace the end of the string
whole_word
If true, shorten the string further to avoid breaking a word in the middle. A word is defined as any string not containing whitespace. If the entire text before the break is a single word, it will have to be broken.

Example:

>>> truncate('Once upon a time in a world far far away', 14)
'Once upon a...'
webhelpers.text.wrap_paragraphs(text, width=72)

Wrap all paragraphs in a text string to the specified width.

width may also be a textwrap.TextWrapper instance, in which case it will be used to do the wrapping. This provides a way to set other options besides the width, and is more efficient when wrapping many texts.

Table Of Contents

This Page