Luke Stebbing avatar Luke Stebbing committed 95a4fe2 Merge

Merge.

Comments (0)

Files changed (14)

   - New helper ``subclasses_only`` to extract the subclasses of an abstract
     base class from a module or iterable.
 
+* webhelpers.pylonslib.flash:
+
+  - Moved to its own module.
+  - Changed ``Flash.__html__()`` implementation.
+
 * webhelpers.pylonslib.grid:
 
   - Bugfixes.
 
+* webhelpers.string24:
+
+  - Delete module. WebHelpers no longer supports Python 2.3.
+
 1.0b3 (2009-12-29)
 ------------------
 * webhelpers.feedgenerator:
 
 * webhelpers.util:
 
-- New helper ``update_params`` to update query parameters in a URL.
+  - New helper ``update_params`` to update query parameters in a URL.
 
 1.0b2 (2009-12-21)
 ------------------

docs/_static/default.css

+/**
+ * Sphinx Doc Design
+ *
+ * Local changes: font size. text-align left.
+ *
+ */
+
+body {
+    font-family: sans-serif;
+    font-size: small;
+    background-color: #11303d;
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+/* :::: LAYOUT :::: */
+
+div.document {
+    background-color: #1c4e63;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+div.body {
+    background-color: white;
+    padding: 0 20px 30px 20px;
+}
+
+div.sphinxsidebarwrapper {
+    padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+    float: left;
+    width: 230px;
+    margin-left: -100%;
+    font-size: 90%;
+}
+
+div.clearer {
+    clear: both;
+}
+
+div.footer {
+    color: #fff;
+    width: 100%;
+    padding: 9px 0 9px 0;
+    text-align: center;
+    font-size: 75%;
+}
+
+div.footer a {
+    color: #fff;
+    text-decoration: underline;
+}
+
+div.related {
+    background-color: #133f52;
+    color: #fff;
+    width: 100%;
+    line-height: 30px;
+    font-size: 90%;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+    margin: 0;
+    padding: 0 0 0 10px;
+    list-style: none;
+}
+
+div.related li {
+    display: inline;
+}
+
+div.related li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+div.related a {
+    color: white;
+}
+
+/* ::: TOC :::: */
+div.sphinxsidebar h3 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: white;
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+    color: white;
+}
+
+div.sphinxsidebar h4 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: white;
+    font-size: 1.3em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+}
+
+div.sphinxsidebar p {
+    color: white;
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    padding: 0;
+    list-style: none;
+    color: white;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+    margin-left: 20px;
+    list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+div.sphinxsidebar a {
+    color: #98dbcc;
+}
+
+div.sphinxsidebar form {
+    margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+/* :::: MODULE CLOUD :::: */
+div.modulecloud {
+    margin: -5px 10px 5px 10px;
+    padding: 10px;
+    line-height: 160%;
+    border: 1px solid #cbe7e5;
+    background-color: #f2fbfd;
+}
+
+div.modulecloud a {
+    padding: 0 5px 0 5px;
+}
+
+/* :::: SEARCH :::: */
+ul.search {
+    margin: 10px 0 0 20px;
+    padding: 0;
+}
+
+ul.search li {
+    padding: 5px 0 5px 20px;
+    background-image: url(file.png);
+    background-repeat: no-repeat;
+    background-position: 0 7px;
+}
+
+ul.search li a {
+    font-weight: bold;
+}
+
+ul.search li div.context {
+    color: #888;
+    margin: 2px 0 0 30px;
+    text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+    font-weight: bold;
+}
+
+/* :::: COMMON FORM STYLES :::: */
+
+div.actions {
+    padding: 5px 10px 5px 10px;
+    border-top: 1px solid #cbe7e5;
+    border-bottom: 1px solid #cbe7e5;
+    background-color: #e0f6f4;
+}
+
+form dl {
+    color: #333;
+}
+
+form dt {
+    clear: both;
+    float: left;
+    min-width: 110px;
+    margin-right: 10px;
+    padding-top: 2px;
+}
+
+input#homepage {
+    display: none;
+}
+
+div.error {
+    margin: 5px 20px 0 0;
+    padding: 5px;
+    border: 1px solid #d00;
+    font-weight: bold;
+}
+
+/* :::: INDEX PAGE :::: */
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.3em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+    font-size: 90%;
+}
+
+/* :::: INDEX STYLES :::: */
+
+table.indextable td {
+    text-align: left;
+    vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+    height: 10px;
+}
+
+table.indextable tr.cap {
+    margin-top: 10px;
+    background-color: #f2f2f2;
+}
+
+img.toggler {
+    margin-right: 3px;
+    margin-top: 3px;
+    cursor: pointer;
+}
+
+form.pfform {
+    margin: 10px 0 20px 0;
+}
+
+/* :::: GLOBAL STYLES :::: */
+
+.docwarning {
+    background-color: #ffe4e4;
+    padding: 10px;
+    margin: 0 -20px 0 -20px;
+    border-bottom: 1px solid #f66;
+}
+
+p.subhead {
+    font-weight: bold;
+    margin-top: 20px;
+}
+
+a {
+    color: #355f7c;
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: 'Trebuchet MS', sans-serif;
+    background-color: #f2f2f2;
+    font-weight: normal;
+    color: #20435c;
+    border-bottom: 1px solid #ccc;
+    margin: 20px -20px 10px -20px;
+    padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 160%; }
+div.body h3 { font-size: 140%; }
+div.body h4 { font-size: 120%; }
+div.body h5 { font-size: 110%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+    color: #c60f0f;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+    visibility: visible;
+}
+
+a.headerlink:hover {
+    background-color: #c60f0f;
+    color: white;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: left;
+    line-height: 130%;
+}
+
+div.body p.caption {
+    text-align: inherit;
+}
+
+div.body td {
+    text-align: left;
+}
+
+ul.fakelist {
+    list-style: none;
+    margin: 10px 0 10px 20px;
+    padding: 0;
+}
+
+.field-list ul {
+    padding-left: 1em;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+/* "Footnotes" heading */
+p.rubric {
+    margin-top: 30px;
+    font-weight: bold;
+}
+
+/* Sidebars */
+
+div.sidebar {
+    margin: 0 0 0.5em 1em;
+    border: 1px solid #ddb;
+    padding: 7px 7px 0 7px;
+    background-color: #ffe;
+    width: 40%;
+    float: right;
+}
+
+p.sidebar-title {
+    font-weight: bold;
+}
+
+/* "Topics" */
+
+div.topic {
+    background-color: #eee;
+    border: 1px solid #ccc;
+    padding: 7px 7px 0 7px;
+    margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+    font-size: 1.1em;
+    font-weight: bold;
+    margin-top: 10px;
+}
+
+/* Admonitions */
+
+div.admonition {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    padding: 7px;
+}
+
+div.admonition dt {
+    font-weight: bold;
+}
+
+div.admonition dl {
+    margin-bottom: 0;
+}
+
+div.admonition p.admonition-title + p {
+    display: inline;
+}
+
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+
+div.warning {
+    background-color: #ffe4e4;
+    border: 1px solid #f66;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+p.admonition-title {
+    margin: 0px 10px 5px 0px;
+    font-weight: bold;
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+div.body p.centered {
+    text-align: center;
+    margin-top: 25px;
+}
+
+table.docutils {
+    border: 0;
+}
+
+table.docutils td, table.docutils th {
+    padding: 1px 8px 1px 0;
+    border-top: 0;
+    border-left: 0;
+    border-right: 0;
+    border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+    border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+    border: 0 !important;
+}
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+dl {
+    margin-bottom: 15px;
+    clear: both;
+}
+
+dd p {
+    margin-top: 0px;
+}
+
+dd ul, dd table {
+    margin-bottom: 10px;
+}
+
+dd {
+    margin-top: 3px;
+    margin-bottom: 10px;
+    margin-left: 30px;
+}
+
+.refcount {
+    color: #060;
+}
+
+dt:target,
+.highlight {
+    background-color: #fbe54e;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+th {
+    text-align: left;
+    padding-right: 5px;
+}
+
+pre {
+    padding: 5px;
+    background-color: #efc;
+    color: #333;
+    border: 1px solid #ac9;
+    border-left: none;
+    border-right: none;
+    overflow: auto;
+}
+
+td.linenos pre {
+    padding: 5px 0px;
+    border: 0;
+    background-color: transparent;
+    color: #aaa;
+}
+
+table.highlighttable {
+    margin-left: 0.5em;
+}
+
+table.highlighttable td {
+    padding: 0 0.5em 0 0.5em;
+}
+
+tt {
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}
+
+tt.descname {
+    background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+}
+
+tt.descclassname {
+    background-color: transparent;
+}
+
+tt.xref, a tt {
+    background-color: transparent;
+    font-weight: bold;
+}
+
+.footnote:target  { background-color: #ffa }
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+    background-color: transparent;
+}
+
+.optional {
+    font-size: 1.3em;
+}
+
+.versionmodified {
+    font-style: italic;
+}
+
+form.comment {
+    margin: 0;
+    padding: 10px 30px 10px 30px;
+    background-color: #eee;
+}
+
+form.comment h3 {
+    background-color: #326591;
+    color: white;
+    margin: -10px -30px 10px -30px;
+    padding: 5px;
+    font-size: 1.4em;
+}
+
+form.comment input,
+form.comment textarea {
+    border: 1px solid #ccc;
+    padding: 2px;
+    font-family: sans-serif;
+    font-size: 100%;
+}
+
+form.comment input[type="text"] {
+    width: 240px;
+}
+
+form.comment textarea {
+    width: 100%;
+    height: 200px;
+    margin-bottom: 10px;
+}
+
+.system-message {
+    background-color: #fda;
+    padding: 5px;
+    border: 3px solid red;
+}
+
+img.math {
+    vertical-align: middle;
+}
+
+div.math p {
+    text-align: center;
+}
+
+span.eqno {
+    float: right;
+}
+
+img.logo {
+    border: 0;
+}
+
+/* :::: PRINT :::: */
+@media print {
+    div.document,
+    div.documentwrapper,
+    div.bodywrapper {
+        margin: 0;
+        width : 100%;
+    }
+
+    div.sphinxsidebar,
+    div.related,
+    div.footer,
+    div#comments div.new-comment-box,
+    #top-link {
+        display: none;
+    }
+}

docs/_templates/index.html

 <img src="_images/webhelpers-logo.png" width="100" height="110" 
     style="float:left; margin-right:1em" />
   
-<p>WebHelpers contains a wide variety of functions for web application
-templates, MVC controller code, and non-web applications.  Main features:
+<p>WebHelpers contains a wide variety of utility functions for web applications
+and other applications. It's pure Python and can be used with any web
+framework.  Version 0.6.x has been used in production sites since July 2008.
+Version 1.0 is almost finished and contains many enhancements. WebHelpers comes
+with an extensive set of doctests and Nose unittests.</p>
 
-    <ul>
-        <li>Works with any web framework</li>
-        <li>An HTML tag generator that smartly escapes text content
-        to prevent cross-site scripting attacks and double-escaping</li>
-        <li>Convenience functions to produce form tags, links, and other common
-        tags.</li>
-        <li>A <code>ModelTags</code> object </li>
-    </ul>
+<p>WebHelpers includes the widely-used HTML tag builder with smart escaping and
+convenience functions for common tags. These ensure the HTML tags are
+syntactically correct and prevent cross-site scripting attacks. Convenience
+functions for form input tags and other common tags are provided.</p> 
 
-It consists of
-several independent subpackages for generating HTML tags and form tags,
-text processing, displaying records a pageful at a time, generating Atom and
-RSS feeds, number formatting and  statistical calculations, handling MIME
-types, and more.  There are also high-level container types, including a value
-counter and accumulator.  There are lists of country names, country codes, US
-states, Canadian provinces, and UK counties.:</p>
-
-<table style="border:outset">
-    <tr><th>constants</th><td>Countries &amp; states for address forms
-    </td></tr>
-    <tr><th>containers</th><td>High-level containers &amp; counters</td></tr>
-    <tr><th>date</th><td>Date/time helpers</td></tr>
-    <tr><th>feedgenerator</th><td>Create Ato and RSS feeds</td></tr>
-    <tr><th>html</th><td>Generate HTML tags and form tags</td></tr>
-    <tr><th>markdown/textile</th><td>Convert
-    wiki-like text to HTML</td></tr>
-    <tr><th>media</th><td>Image file calculations</td></tr>
-    <tr><th>mimehelper</th><td>MIME types</td></tr>
-    <tr><th>number</th><td>Formatters and statistics</td></tr>
-    <tr><th>paginate</th><td>Display records a pageful at a time
-    </td></tr>
-    <tr><th>pylonslib</th><td>Helpers for Pylons</td></tr>
-    <tr><th>text</th><td>Text processing</td></tr>
-</table>
-
-<br clear="all" />
-
-
+<p>Other helpers
+perform text processing, display records a pageful at a time, generate Atom/RSS
+feeds with geographical (GIS) data, handle MIME types, calculate statistics,
+and more.  There are also high-level container types, including a value counter
+and accumulator.  There are lists of country names, country codes, US states,
+Canadian provinces, and UK counties.</p>
 
 <p>WebHelpers is pure Python and has no dependencies.  However, a few
 helpers depend on 
 <a href="http://routes.groovie.org/">Routes</a>, 
-, 
 <a href="http://python.org/pypi/Unidecode/">unidecode</a>, 
-<a href="http://pythonpaste.org/webob/">WebOb</a>
-as noted in their documentation.  The Pylons helpers are designed for <a
-href="http://pylonshq.com/">Pylons</a>' request/response/session objects but
-can easily be ported to another web framework.  WebHelpers comes with an
-extensive set of unit tests.</p>
+<a href="http://pythonpaste.org/webob/">WebOb</a>, or
+<a href="http://pylonshq.com/">Pylons</a>, or
+as noted in their documentation.</p>
 
-<p>For support/question/patches, please use the `
-<a href="http://groups.google.com/group/pylons-discuss">Pylons mailing list</a>.</p>
+<p>For support/question/patches, please use the
+<a href="http://groups.google.com/group/pylons-discuss">pylons-discuss</a>
+mailing list.</p>
 
-<h2>New features</h2>
+<h2>Upgrading</h2>
 
-<div style="font-size:smaller">
+<p>The helpers deprecated in 0.6 have been deleted in 1.0.  This includes the
+entire Rails suite, Prototype, and Scriptaculous. If you're still using these
+helpers, stick with version 0.6.4.</p>
 
-<p>Version 1.0b1 (YYYY-MM-DD -- not released yet)</p>
-
-<ul>
-    <li>Documentation rewrite.</li>
-    <li>Many new helpers in <code>html.converters</code>,
-    <code>html.tags</code>, <code>html.tools</code>, <code>paginate</code>,
-    <code>pylonslib</code>, <code>text</code>.</li>
-    <li>Delete deprecated subpackages: <code>commands</code>,
-    <code>hinclude</code>, <code>htmlgen</code>, <code>pagination</code>,
-    <code>rails</code>. <strong>CAUTION:</strong> if using these helpers, stick
-    to WebHelpers 0.6.4.</li>
-</ul>
-
-<p>Version 0.6.4 (2008-12-02)
-
-<ul>
-    <li>Several form helpers have magic ID attribute.</li>
-    <li>Bugfixes in <code>ModelTags.select</code>.</li>
-</ul>
-
-</div>
+<p>WebHelpers requires Python 2.4 or later. It has not been tested with Python
+3 yet.</p>
 
 <p><a href="changes.html">Full changelog</a></p>
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-#html_static_path = ['_static']
+html_static_path = ['_static']
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.

docs/contents.rst

    modules/text
    modules/util
 
-Minor subpackages
-+++++++++++++++++
+Non-essential subpackages
++++++++++++++++++++++++++
 
 .. toctree::
-  :maxdepth: 1
+    :maxdepth: 2
 
-  modules/markdown
-  modules/textile
+    modules/markdown
+    modules/textile
+
 
 Metadata
 ++++++++

docs/index.txt

-Untested.)WebHelpers
-++++++++++++
-
-WebHelpers is package aimed at providing helper functions for use within web applications.
-
-These functions are intended to ease web development with template languages by removing common view logic and
-encapsulating it in re-usable modules as well as occasionally providing objects for use within controllers to
-assist with common web development paradigms.
-
-For support/question/patches, please use the `Pylons mailing list <http://groups.google.com/group/pylons-discuss>`_.
-
-*Requirements:* Some WebHelper functions require `Routes <http://routes.groovie.org/>`_ to be active in the
-framework for a variety of functions. Currently `Pylons <http://pylons.groovie.org/>`_, `TurboGears <http://trac.turbogears.org/turbogears/wiki/RoutesIntegration>`_,
-and `Aquarium <http://aquarium.sourceforge.net/>`_ support Routes.

docs/modules/markdown.rst

 :mod:`webhelpers.markdown`
-================================================
+==========================
 
-.. automodule:: webhelpers.markdown
+``webhelpers.markdown`` is a copy of Markdown 1.7, used as a fallback for
+``webhelpers.html.converters.markdown()`` if the full Markdown package is not
+installed. See the Markdown_ website for documentation on the Markdown
+format and this module.  Markdown is now at version 2.x and contains new
+features and plugins which are too big to include in WebHelpers. There is also
+an alternate implementation called Markdown2.  Both are available on PyPI.  See
+the ``markdown()`` documentation for how to use them with WebHelpers.
 
-.. currentmodule:: webhelpers.markdown
+.. _Markdown: http://markdown.org/
+
+..
+    .. automodule:: webhelpers.markdown
+
+    .. currentmodule:: webhelpers.markdown

docs/modules/pylonslib.rst

 .. automodule:: webhelpers.pylonslib
 
 .. currentmodule:: webhelpers.pylonslib
+
+:mod:`webhelpers.pylonslib.flash`
+================================================
+
+.. automodule:: webhelpers.pylonslib.flash
+
+.. currentmodule:: webhelpers.pylonslib.flash
+
+.. autoclass:: Flash
+    :members:

docs/modules/textile.rst

 :mod:`webhelpers.textile`
-================================================
+=========================
 
-.. automodule:: webhelpers.textile
+``webhelpers.textile`` is a copy of Textile, used by
+``webhelpers.html.converters.textilize()``.  See the Textile_ site for
+documentation on the Textile format and this module.
 
-.. currentmodule:: webhelpers.textile
+.. _Textile:  http://textile.org/
+
+..
+    .. automodule:: webhelpers.textile
+
+    .. currentmodule:: webhelpers.textile

webhelpers/html/builder.py

 
 But these return an ordinary string which is prone to double-escaping later::
 
-    "\n".join([literal('<span class="foo">Foo!</span>'), literal('Bar!')])
+    "\\n".join([literal('<span class="foo">Foo!</span>'), literal('Bar!')])
     "%s %s" % (literal("16"), literal("&lt;em&gt;kg&lt;/em&gt;"))
 
 Third-party libraries that don't want to import ``literal`` and thus avoid a

webhelpers/paginate.py

 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 import re
+from string import Template
 import warnings
 
-# Use templating for the .pager() [available since Python 2.4].
-# Otherwise the Template module is provided by the string24.py
-# for Python 2.3
-try:
-    from string import Template
-except ImportError:
-    from webhelpers.string24 import Template
-
 # Import the webhelpers to create URLs
 from webhelpers.html import literal, HTML
 

webhelpers/pylonslib/__init__.py

-"""Helpers for the Pylons web framework
+"""Helpers for the `Pylons <http://pylonshq.com>`_ web framework
 
 These helpers depend on Pylons' ``request``, ``response``, ``session``
 objects or some other aspect of Pylons.  Most of them can be easily ported to
 # modules should be importable on any Python system for the standard
 # regression tests.
 
-class Message(object):
-    def __init__(self, category, message):
-        self.category=category
-        self.message=message
-
-    def __str__(self):
-        return self.message
-
-    __unicode__ = __str__
-
-    @property
-    def __html__(self):
-        return getattr(self.message, '__html__')
-
-
-class Flash(object):
-    """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:
-    
-    .. code-block:: mako
-    
-        <% 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:
-
-    .. code-block:: css
-
-        ul#flash-messages {
-            color: red;
-            background-color: #FFFFCC;
-            font-size: larger;
-            font-style: italic;
-            margin-left: 40px;
-            padding: 4px;
-            list-style: none;
-            }
-
-    Multiple flash objects
-    ======================
-
-    You can define multiple flash objects in your application to display
-    different kinds of messages at different places on the page.  For instance,
-    you might use the main flash object for general messages, and a second
-    flash object for "Added dookickey" / "Removed doohickey" messages next to a
-    doohickey manager.
-
-    Message categories
-    ==================
-
-    WebHelpers 1.0 adds message categories, contributed by Wichert Akkerman.
-    These work like severity levels in Python's logging system.  The standard
-    categories are "*warning*", "*notice*", "*error*", and "*success*", with
-    the default being "*notice*".  The category is available in the message's
-    ``.category`` attribute, and is normally used to set the container's CSS
-    class.  Unlike the logging system, the flash object does not filter out
-    messages below a certain level; it returns all messages set. 
-
-    You can change the standard categories by overriding the ``.categories``
-    and ``.default_category`` class attributes.
-
-    Note that messages are _not_ grouped by category, nor is it possible to 
-    pop one category of messages while leaving the others.  If you want to 
-    group different kinds of messages together, you should use multiple flash
-    objects.
-
-    Category example
-    ----------------
-
-    Lets show a standard way of using flash messages in your site: we will
-    demonstrate *self-healing messages* (similar to what Growl does on OSX)
-    to show messages in a site.
-
-    To send a message from python just call the flash helper method::
-
-       from myapp.lib.helpers import flash
-
-       flash(u"Settings have been saved")
-
-    This will tell the system to show a message in the rendered page. If you need
-    more control you can specify a message category as well: one of *warning*,
-    *notice*, *error* or *success*. The default category is *notice*. For example::
-
-       from myapp.lib.helpers import flash
-
-       flash(u"Failed to send confirmation email", "warning")
-
-    We will use a very simple markup style: messages will be placed in a ``div``
-    with id ``selfHealingFeedback`` at the end of the document body. The messages
-    are standard paragraphs with a class indicating the message category. For
-    example::
-
-      <html>
-        <body>
-          <div id="content">
-            ...
-            ...
-          </div>
-          <div id="selfHealingFeedback">
-            <p class="success">Succesfully updated your settings</p>
-            <p class="warning">Failed to send confirmation email</p>
-          </div>
-        </body>
-      </html>
-
-    This can easily created from a template. If you are using Genshi this
-    should work:
-
-      <div id="selfHealingFeedback">
-        <p class="notice" py:for="message in h.flash.pop_messages()"
-           py:attrs="{'class' : message.category}" py:content="message">
-          This is a notice.
-        </p>
-      </div>
-
-    The needed CSS is very simple::
-
-        #selfHealingFeedback {
-            position: fixed;
-            top: 20px;
-            left: 20px;
-            z-index: 2000;
-        }
-
-        #selfHealingFeedback p {
-            margin-bottom: 10px;
-            width: 250px;
-            opacity: 0.93;
-        }
-
-        p.notice,p.error,p.success,p.warning {
-            border: 3px solid silver;
-            padding: 10px;
-            -webkit-border-radius: 3px;
-            -moz-border-radius: 3px;
-            border-radius: 3px;
-            -webkit-box-shadow: 0 0 5px silver;
-        }
-
-    Choosing different colours for the categories is left as an excersize
-    for the reader.
-
-    Next we create the javascript that will manage the needed behaviour (this
-    implementation is based on jQuery)::
-
-        function _SetupMessage(el) {
-            var remover = function () {
-                msg.animate({opacity: 0}, "slow")
-                   .slideUp("slow", function() { msg.remove() }); };
-
-            msg.data("healtimer", setTimeout(remover, 10000))
-               .click(function() { clearTimeout(msg.data("healtimer")); remover(); });
-        }
-
-        function ShowMessage(message, category) {
-            if (!category)
-                category="notice";
-
-            var container = $("#selfHealingFeedback");
-
-            if (!container.length)
-                container=$("<div id='selfHealingFeedback'/>").appendTo("body");
-
-            var msg = $("<p/>").addClass(category).html(message);
-            SetupMessage(msg);
-            msg.appendTo(container);
-        }
-
-        $(document).ready(function() {
-            $("#selfHealingFeedback p").each(function() { SetupMessage($(this)); });
-        }
-
-    The ``SetupMessage`` function configures the desired behaviour: a message
-    disappears after 10 seconds, or if you click on it. Removal is done using
-    a simple animation to avoid messages jumping around on the screen.
-
-    This function is called for all messages as soon as the document has fully
-    loaded. The ``ShowMessage`` function works exactly like the ``flash`` method
-    in python: you can call it with a message and optionally a category and it
-    will pop up a new message.
-
-    JSON integration
-    ----------------
-
-    It is not unusal to perform a remote task using a JSON call and show a
-    result message to the user. This can easily be done using a simple wrapper
-    around the ShowMessage method::
-
-        function ShowJSONResponse(info) {
-            if (!info.message)
-                return;
-
-            ShowMessage(info.message, info.message_category);
-        }
-
-    You can use this direct as the success callback for the jQuery AJAX method::
-
-       $.ajax({type: "POST",
-               url:  "http://your.domain/call/json",
-               dataType: "json",
-               success: ShowJSONResponse
-       });
-
-    if you need to perform extra work in your callback method you can call
-    it yourself as well, for example::
-
-       <form action="http://your.domain/call/form">
-         <input type="hidden" name="json_url" value="http://your.domain/call/json">
-         <button>Submit</button>
-       </form>
-
-       <sript type="text/javascript">
-          $(document).ready(function() {
-              $("button").click(function() {
-                  var button = $(this);
-
-                  button.addClass("processing");
-                  $.ajax({type: "POST",
-                          url:  this.form["json_url"].value,
-                          dataType: "json",
-                          success: function(data, status) {
-                              button.removeClass("processing");
-                              ShowJSONResponse(data);
-                           },
-                           error: function(request, status, error) {
-                              button.removeClass("processing");
-                              ShowMessage("JSON call failed", "error");
-                           }
-                  });
-
-                  return false;
-              });
-          });
-       </script>
-
-    This sets up a simple form which can be submitted normally by non-javascript
-    enabled browsers. If a user does hava javascript an AJAX call will be made
-    to the server and the result will be shown in a message. While the call is
-    active the button will be marked with a *processing* class.
-
-    The server can return a message by including a ``message`` field in its
-    response. Optionally a ``message_category`` field can also be included
-    which will be used to determine the message category. For example::
-
-        @jsonify
-        def handler(self):
-           ..
-           ..
-           return dict(message=u"Settings succesfully updated") 
-    """
-    
-    # List of allowed categories.  If None, allow any category.
-    categories = ["warning", "notice", "error", "success"]
-    
-    # Default category if none is specified.
-    default_category = "notice"
-
-    def __init__(self, session_key="flash"):
-        self.session_key = session_key
-
-    def __call__(self, message, category=None):
-        if not category:
-            category = self.default_category
-        elif self.categories and category not in self.categories:
-            raise ValueError("unrecognized category '%s'" % category)
-        # Don't store Message objects in the session, to avoid unpickling
-        # errors in edge cases.
-        from pylons import session
-        session.setdefault(self.session_key, []).append((category, message))
-        session.save()
-
-    def pop_messages(self):
-        from pylons import session
-        messages = session.pop(self.session_key, [])
-        session.save()
-        return [Message(*m) for m in messages]
+# Backward compatibility
+from webhelpers.pylonslib.flash import *

webhelpers/pylonslib/flash.py

+"""Accumulate messages to show on the next page request.
+
+The ``Flash`` 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".
+
+THE IMPLEMENTATION DEPENDS ON PYLONS.  However, it can easily be adapted
+for another web framework.
+
+A typical Pylons application instantiates a ``Flash`` object in 
+myapp/lib/helpers.py::
+
+    from webhelpers.pylonslib.flash 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, call the instance::
+
+    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:
+
+.. code-block:: mako
+
+    <% 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:
+
+.. code-block:: css
+
+    ul#flash-messages {
+        color: red;
+        background-color: #FFFFCC;
+        font-size: larger;
+        font-style: italic;
+        margin-left: 40px;
+        padding: 4px;
+        list-style: none;
+        }
+
+Multiple flash objects
+======================
+
+You can define multiple flash objects in your application to display
+different kinds of messages at different places on the page.  For instance,
+you might use the main flash object for general messages, and a second
+flash object for "Added dookickey" / "Removed doohickey" messages next to a
+doohickey manager.
+
+Message categories
+==================
+
+WebHelpers 1.0 adds message categories, contributed by Wichert Akkerman.
+These work like severity levels in Python's logging system.  The standard
+categories are "*warning*", "*notice*", "*error*", and "*success*", with
+the default being "*notice*".  The category is available in the message's
+``.category`` attribute, and is normally used to set the container's CSS
+class.  Unlike the logging system, the flash object does not filter out
+messages below a certain level; it returns all messages set. 
+
+You can change the standard categories by overriding the ``.categories``
+and ``.default_category`` class attributes.
+
+Note that messages are _not_ grouped by category, nor is it possible to 
+pop one category of messages while leaving the others.  If you want to 
+group different kinds of messages together, you should use multiple flash
+objects.
+
+Category example
+----------------
+
+Let's show a standard way of using flash messages in your site: we will
+demonstrate *self-healing messages* (similar to what Growl does on OSX)
+to show messages in a site.
+
+To send a message from python just call the flash helper method::
+
+   h.flash(u"Settings have been saved")
+
+This will tell the system to show a message in the rendered page. If you need
+more control you can specify a message category as well: one of *warning*,
+*notice*, *error* or *success*. The default category is *notice*. For example::
+
+   h.flash(u"Failed to send confirmation email", "warning")
+
+We will use a very simple markup style: messages will be placed in a ``div``
+with id ``selfHealingFeedback`` at the end of the document body. The messages
+are standard paragraphs with a class indicating the message category. For
+example::
+
+  <html>
+    <body>
+      <div id="content">
+        ...
+        ...
+      </div>
+      <div id="selfHealingFeedback">
+        <p class="success">Succesfully updated your settings</p>
+        <p class="warning">Failed to send confirmation email</p>
+      </div>
+    </body>
+  </html>
+
+This can easily created from a template. If you are using Genshi this
+should work:
+
+.. code-block: html
+
+  <div id="selfHealingFeedback">
+    <p class="notice" py:for="message in h.flash.pop_messages()"
+       py:attrs="{'class' : message.category}" py:content="message">
+      This is a notice.
+    </p>
+  </div>
+
+The needed CSS is very simple:
+
+.. code-block: css
+
+    #selfHealingFeedback {
+        position: fixed;
+        top: 20px;
+        left: 20px;
+        z-index: 2000;
+    }
+
+    #selfHealingFeedback p {
+        margin-bottom: 10px;
+        width: 250px;
+        opacity: 0.93;
+    }
+
+    p.notice,p.error,p.success,p.warning {
+        border: 3px solid silver;
+        padding: 10px;
+        -webkit-border-radius: 3px;
+        -moz-border-radius: 3px;
+        border-radius: 3px;
+        -webkit-box-shadow: 0 0 5px silver;
+    }
+
+Choosing different colours for the categories is left as an exersise
+for the reader.
+
+Next we create the javascript that will manage the needed behaviour (this
+implementation is based on jQuery)::
+
+    function _SetupMessage(el) {
+        var remover = function () {
+            msg.animate({opacity: 0}, "slow")
+               .slideUp("slow", function() { msg.remove() }); };
+
+        msg.data("healtimer", setTimeout(remover, 10000))
+           .click(function() { clearTimeout(msg.data("healtimer")); remover(); });
+    }
+
+    function ShowMessage(message, category) {
+        if (!category)
+            category="notice";
+
+        var container = $("#selfHealingFeedback");
+
+        if (!container.length)
+            container=$("<div id='selfHealingFeedback'/>").appendTo("body");
+
+        var msg = $("<p/>").addClass(category).html(message);
+        SetupMessage(msg);
+        msg.appendTo(container);
+    }
+
+    $(document).ready(function() {
+        $("#selfHealingFeedback p").each(function() { SetupMessage($(this)); });
+    }
+
+The ``SetupMessage`` function configures the desired behaviour: a message
+disappears after 10 seconds, or if you click on it. Removal is done using
+a simple animation to avoid messages jumping around on the screen.
+
+This function is called for all messages as soon as the document has fully
+loaded. The ``ShowMessage`` function works exactly like the ``flash`` method
+in python: you can call it with a message and optionally a category and it
+will pop up a new message.
+
+JSON integration
+----------------
+
+It is not unusal to perform a remote task using a JSON call and show a
+result message to the user. This can easily be done using a simple wrapper
+around the ShowMessage method::
+
+    function ShowJSONResponse(info) {
+        if (!info.message)
+            return;
+
+        ShowMessage(info.message, info.message_category);
+    }
+
+You can use this direct as the success callback for the jQuery AJAX method::
+
+   $.ajax({type: "POST",
+           url:  "http://your.domain/call/json",
+           dataType: "json",
+           success: ShowJSONResponse
+   });
+
+if you need to perform extra work in your callback method you can call
+it yourself as well, for example::
+
+   <form action="http://your.domain/call/form">
+     <input type="hidden" name="json_url" value="http://your.domain/call/json">
+     <button>Submit</button>
+   </form>
+
+   <sript type="text/javascript">
+      $(document).ready(function() {
+          $("button").click(function() {
+              var button = $(this);
+
+              button.addClass("processing");
+              $.ajax({type: "POST",
+                      url:  this.form["json_url"].value,
+                      dataType: "json",
+                      success: function(data, status) {
+                          button.removeClass("processing");
+                          ShowJSONResponse(data);
+                       },
+                       error: function(request, status, error) {
+                          button.removeClass("processing");
+                          ShowMessage("JSON call failed", "error");
+                       }
+              });
+
+              return false;
+          });
+      });
+   </script>
+
+This sets up a simple form which can be submitted normally by non-javascript
+enabled browsers. If a user does hava javascript an AJAX call will be made
+to the server and the result will be shown in a message. While the call is
+active the button will be marked with a *processing* class.
+
+The server can return a message by including a ``message`` field in its
+response. Optionally a ``message_category`` field can also be included
+which will be used to determine the message category. For example::
+
+    @jsonify
+    def handler(self):
+       ..
+       ..
+       return dict(message=u"Settings succesfully updated")
+"""
+
+# Do not import Pylons at module level; only within functions.  All WebHelpers
+# modules should be importable on any Python system for the standard
+# regression tests.
+
+from webhelpers.html import escape
+
+__all__ = ["Flash", "Message"]
+
+class Message(object):
+    """A message returned by ``Flash.pop_messages()``.
+
+    ``Message`` instances have the following attributes:
+
+    * ``message``: the message text.
+    * ``category``: the category specified when the message was created.
+
+    Calling ``str(message)`` ``unicode(message)``, or ``message.__html__()`` 
+    returns the message text. (The latter returns an escaped literal
+    unless the message is already a literal; see 
+    ``webhelpers.html.builder``.)
+    """
+
+    def __init__(self, category, message):
+        self.category=category
+        self.message=message
+
+    def __str__(self):
+        return self.message
+
+    __unicode__ = __str__
+
+    def __html__(self):
+        return escape(self.message)
+
+
+class Flash(object):
+    """Accumulate a list of messages to show at the next page request.
+    """
+    
+    # List of allowed categories.  If None, allow any category.
+    categories = ["warning", "notice", "error", "success"]
+    
+    # Default category if none is specified.
+    default_category = "notice"
+
+    def __init__(self, session_key="flash"):
+        """Instantiate a ``Flash`` object.
+
+        ``session_key`` is the key to save the messages under in the user's
+        session.
+        """
+        self.session_key = session_key
+
+    def __call__(self, message, category=None):
+        """Add a message to the session.
+
+        ``message`` is the message text.
+
+        ``category`` is the message's category. If not specified, the default
+        category will be used.  Raise ``ValueError`` if the category is not
+        in the list of allowed categories.
+        """
+        if not category:
+            category = self.default_category
+        elif self.categories and category not in self.categories:
+            raise ValueError("unrecognized category '%s'" % category)
+        # Don't store Message objects in the session, to avoid unpickling
+        # errors in edge cases.
+        from pylons import session
+        session.setdefault(self.session_key, []).append((category, message))
+        session.save()
+
+    def pop_messages(self):
+        """Return all accumulated messages and delete them from the session.
+
+        The return value is a list of ``Message`` objects.
+        """
+        from pylons import session
+        messages = session.pop(self.session_key, [])
+        session.save()
+        return [Message(*m) for m in messages]

webhelpers/string24.py

-"""A collection of string operations (most are no longer used).
-
-Warning: most of the code you see here isn't normally used nowadays.
-Beginning with Python 1.6, many of these functions are implemented as
-methods on the standard string object. They used to be implemented by
-a built-in module called strop, but strop is now obsolete itself.
-
-Public module variables:
-
-whitespace -- a string containing all characters considered whitespace
-lowercase -- a string containing all characters considered lowercase letters
-uppercase -- a string containing all characters considered uppercase letters
-letters -- a string containing all characters considered letters
-digits -- a string containing all characters considered decimal digits
-hexdigits -- a string containing all characters considered hexadecimal digits
-octdigits -- a string containing all characters considered octal digits
-punctuation -- a string containing all characters considered punctuation
-printable -- a string containing all characters considered printable
-
-"""
-
-# Some strings for ctype-style character classification
-whitespace = ' \t\n\r\v\f'
-lowercase = 'abcdefghijklmnopqrstuvwxyz'
-uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-letters = lowercase + uppercase
-ascii_lowercase = lowercase
-ascii_uppercase = uppercase
-ascii_letters = ascii_lowercase + ascii_uppercase
-digits = '0123456789'
-hexdigits = digits + 'abcdef' + 'ABCDEF'
-octdigits = '01234567'
-punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
-printable = digits + letters + punctuation + whitespace
-
-# Case conversion helpers
-# Use str to convert Unicode literal in case of -U
-# Note that Cookie.py bogusly uses _idmap :(
-l = map(chr, xrange(256))
-_idmap = str('').join(l)
-del l
-
-# Functions which aren't available as string methods.
-
-# Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def".
-# See also regsub.capwords().
-def capwords(s, sep=None):
-    """capwords(s, [sep]) -> string
-
-    Split the argument into words using split, capitalize each
-    word using capitalize, and join the capitalized words using
-    join. Note that this replaces runs of whitespace characters by
-    a single space.
-
-    """
-    return (sep or ' ').join([x.capitalize() for x in s.split(sep)])
-
-
-# Construct a translation string
-_idmapL = None
-def maketrans(fromstr, tostr):
-    """maketrans(frm, to) -> string
-
-    Return a translation table (a string of 256 bytes long)
-    suitable for use in string.translate.  The strings frm and to
-    must be of the same length.
-
-    """
-    if len(fromstr) != len(tostr):
-        raise ValueError, "maketrans arguments must have same length"
-    global _idmapL
-    if not _idmapL:
-        _idmapL = map(None, _idmap)
-    L = _idmapL[:]
-    fromstr = map(ord, fromstr)
-    for i in range(len(fromstr)):
-        L[fromstr[i]] = tostr[i]
-    return ''.join(L)
-
-
-
-####################################################################
-import re as _re
-
-class _multimap:
-    """Helper class for combining multiple mappings.
-
-    Used by .{safe_,}substitute() to combine the mapping and keyword
-    arguments.
-    """
-    def __init__(self, primary, secondary):
-        self._primary = primary
-        self._secondary = secondary
-
-    def __getitem__(self, key):
-        try:
-            return self._primary[key]
-        except KeyError:
-            return self._secondary[key]
-
-
-class _TemplateMetaclass(type):
-    pattern = r"""
-    %(delim)s(?:
-      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
-      (?P<named>%(id)s)      |   # delimiter and a Python identifier
-      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
-      (?P<invalid>)              # Other ill-formed delimiter exprs
-    )
-    """
-
-    def __init__(cls, name, bases, dct):
-        super(_TemplateMetaclass, cls).__init__(name, bases, dct)
-        if 'pattern' in dct:
-            pattern = cls.pattern
-        else:
-            pattern = _TemplateMetaclass.pattern % {
-                'delim' : _re.escape(cls.delimiter),
-                'id'    : cls.idpattern,
-                }
-        cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
-
-
-class Template:
-    """A string class for supporting $-substitutions."""
-    __metaclass__ = _TemplateMetaclass
-
-    delimiter = '$'
-    idpattern = r'[_a-z][_a-z0-9]*'
-
-    def __init__(self, template):
-        self.template = template
-
-    # Search for $$, $identifier, ${identifier}, and any bare $'s
-
-    def _invalid(self, mo):
-        i = mo.start('invalid')
-        lines = self.template[:i].splitlines(True)
-        if not lines:
-            colno = 1
-            lineno = 1
-        else:
-            colno = i - len(''.join(lines[:-1]))
-            lineno = len(lines)
-        raise ValueError('Invalid placeholder in string: line %d, col %d' %
-                         (lineno, colno))
-
-    def substitute(self, *args, **kws):
-        if len(args) > 1:
-            raise TypeError('Too many positional arguments')
-        if not args:
-            mapping = kws
-        elif kws:
-            mapping = _multimap(kws, args[0])
-        else:
-            mapping = args[0]
-        # Helper function for .sub()
-        def convert(mo):
-            # Check the most common path first.
-            named = mo.group('named') or mo.group('braced')
-            if named is not None:
-                val = mapping[named]
-                # We use this idiom instead of str() because the latter will
-                # fail if val is a Unicode containing non-ASCII characters.
-                return '%s' % val
-            if mo.group('escaped') is not None:
-                return self.delimiter
-            if mo.group('invalid') is not None:
-                self._invalid(mo)
-            raise ValueError('Unrecognized named group in pattern',
-                             self.pattern)
-        return self.pattern.sub(convert, self.template)
-
-    def safe_substitute(self, *args, **kws):
-        if len(args) > 1:
-            raise TypeError('Too many positional arguments')
-        if not args:
-            mapping = kws
-        elif kws:
-            mapping = _multimap(kws, args[0])
-        else:
-            mapping = args[0]
-        # Helper function for .sub()
-        def convert(mo):
-            named = mo.group('named')
-            if named is not None:
-                try:
-                    # We use this idiom instead of str() because the latter
-                    # will fail if val is a Unicode containing non-ASCII
-                    return '%s' % mapping[named]
-                except KeyError:
-                    return self.delimiter + named
-            braced = mo.group('braced')
-            if braced is not None:
-                try:
-                    return '%s' % mapping[braced]
-                except KeyError:
-                    return self.delimiter + '{' + braced + '}'
-            if mo.group('escaped') is not None:
-                return self.delimiter
-            if mo.group('invalid') is not None:
-                return self.delimiter
-            raise ValueError('Unrecognized named group in pattern',
-                             self.pattern)
-        return self.pattern.sub(convert, self.template)
-
-
-
-####################################################################
-# NOTE: Everything below here is deprecated.  Use string methods instead.
-# This stuff will go away in Python 3.0.
-
-# Backward compatible names for exceptions
-index_error = ValueError
-atoi_error = ValueError
-atof_error = ValueError
-atol_error = ValueError
-
-# convert UPPER CASE letters to lower case
-def lower(s):
-    """lower(s) -> string
-
-    Return a copy of the string s converted to lowercase.
-
-    """
-    return s.lower()
-
-# Convert lower case letters to UPPER CASE
-def upper(s):
-    """upper(s) -> string
-
-    Return a copy of the string s converted to uppercase.
-
-    """
-    return s.upper()
-
-# Swap lower case letters and UPPER CASE
-def swapcase(s):
-    """swapcase(s) -> string
-
-    Return a copy of the string s with upper case characters
-    converted to lowercase and vice versa.
-
-    """
-    return s.swapcase()
-
-# Strip leading and trailing tabs and spaces
-def strip(s, chars=None):
-    """strip(s [,chars]) -> string
-
-    Return a copy of the string s with leading and trailing
-    whitespace removed.
-    If chars is given and not None, remove characters in chars instead.
-    If chars is unicode, S will be converted to unicode before stripping.
-
-    """
-    return s.strip(chars)
-
-# Strip leading tabs and spaces
-def lstrip(s, chars=None):
-    """lstrip(s [,chars]) -> string
-
-    Return a copy of the string s with leading whitespace removed.
-    If chars is given and not None, remove characters in chars instead.
-
-    """
-    return s.lstrip(chars)
-
-# Strip trailing tabs and spaces
-def rstrip(s, chars=None):
-    """rstrip(s [,chars]) -> string
-
-    Return a copy of the string s with trailing whitespace removed.
-    If chars is given and not None, remove characters in chars instead.
-
-    """
-    return s.rstrip(chars)
-
-
-# Split a string into a list of space/tab-separated words
-def split(s, sep=None, maxsplit=-1):
-    """split(s [,sep [,maxsplit]]) -> list of strings
-
-    Return a list of the words in the string s, using sep as the
-    delimiter string.  If maxsplit is given, splits at no more than
-    maxsplit places (resulting in at most maxsplit+1 words).  If sep
-    is not specified or is None, any whitespace string is a separator.
-
-    (split and splitfields are synonymous)
-
-    """
-    return s.split(sep, maxsplit)
-splitfields = split
-
-# Split a string into a list of space/tab-separated words
-def rsplit(s, sep=None, maxsplit=-1):
-    """rsplit(s [,sep [,maxsplit]]) -> list of strings
-
-    Return a list of the words in the string s, using sep as the
-    delimiter string, starting at the end of the string and working
-    to the front.  If maxsplit is given, at most maxsplit splits are
-    done. If sep is not specified or is None, any whitespace string
-    is a separator.
-    """
-    return s.rsplit(sep, maxsplit)
-
-# Join fields with optional separator
-def join(words, sep = ' '):
-    """join(list [,sep]) -> string
-
-    Return a string composed of the words in list, with
-    intervening occurrences of sep.  The default separator is a
-    single space.
-
-    (joinfields and join are synonymous)
-
-    """
-    return sep.join(words)
-joinfields = join
-
-# Find substring, raise exception if not found
-def index(s, *args):
-    """index(s, sub [,start [,end]]) -> int
-
-    Like find but raises ValueError when the substring is not found.
-
-    """
-    return s.index(*args)
-
-# Find last substring, raise exception if not found
-def rindex(s, *args):
-    """rindex(s, sub [,start [,end]]) -> int
-
-    Like rfind but raises ValueError when the substring is not found.
-
-    """
-    return s.rindex(*args)
-
-# Count non-overlapping occurrences of substring
-def count(s, *args):
-    """count(s, sub[, start[,end]]) -> int
-
-    Return the number of occurrences of substring sub in string
-    s[start:end].  Optional arguments start and end are
-    interpreted as in slice notation.
-
-    """
-    return s.count(*args)
-
-# Find substring, return -1 if not found
-def find(s, *args):
-    """find(s, sub [,start [,end]]) -> in
-
-    Return the lowest index in s where substring sub is found,
-    such that sub is contained within s[start,end].  Optional
-    arguments start and end are interpreted as in slice notation.
-
-    Return -1 on failure.
-
-    """
-    return s.find(*args)
-
-# Find last substring, return -1 if not found
-def rfind(s, *args):
-    """rfind(s, sub [,start [,end]]) -> int
-
-    Return the highest index in s where substring sub is found,
-    such that sub is contained within s[start,end].  Optional
-    arguments start and end are interpreted as in slice notation.
-
-    Return -1 on failure.
-
-    """
-    return s.rfind(*args)
-
-# for a bit of speed
-_float = float
-_int = int
-_long = long
-
-# Convert string to float
-def atof(s):
-    """atof(s) -> float
-
-    Return the floating point number represented by the string s.
-
-    """
-    return _float(s)
-
-
-# Convert string to integer
-def atoi(s , base=10):
-    """atoi(s [,base]) -> int
-
-    Return the integer represented by the string s in the given
-    base, which defaults to 10.  The string s must consist of one
-    or more digits, possibly preceded by a sign.  If base is 0, it
-    is chosen from the leading characters of s, 0 for octal, 0x or
-    0X for hexadecimal.  If base is 16, a preceding 0x or 0X is
-    accepted.
-
-    """
-    return _int(s, base)
-
-
-# Convert string to long integer
-def atol(s, base=10):
-    """atol(s [,base]) -> long
-
-    Return the long integer represented by the string s in the
-    given base, which defaults to 10.  The string s must consist
-    of one or more digits, possibly preceded by a sign.  If base
-    is 0, it is chosen from the leading characters of s, 0 for
-    octal, 0x or 0X for hexadecimal.  If base is 16, a preceding
-    0x or 0X is accepted.  A trailing L or l is not accepted,
-    unless base is 0.
-
-    """
-    return _long(s, base)
-
-
-# Left-justify a string
-def ljust(s, width, *args):
-    """ljust(s, width[, fillchar]) -> string
-
-    Return a left-justified version of s, in a field of the
-    specified width, padded with spaces as needed.  The string is
-    never truncated.  If specified the fillchar is used instead of spaces.
-
-    """
-    return s.ljust(width, *args)
-
-# Right-justify a string
-def rjust(s, width, *args):
-    """rjust(s, width[, fillchar]) -> string
-
-    Return a right-justified version of s, in a field of the
-    specified width, padded with spaces as needed.  The string is
-    never truncated.  If specified the fillchar is used instead of spaces.
-
-    """
-    return s.rjust(width, *args)
-
-# Center a string
-def center(s, width, *args):
-    """center(s, width[, fillchar]) -> string
-
-    Return a center version of s, in a field of the specified
-    width. padded with spaces as needed.  The string is never
-    truncated.  If specified the fillchar is used instead of spaces.
-
-    """
-    return s.center(width, *args)
-
-# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
-# Decadent feature: the argument may be a string or a number
-# (Use of this is deprecated; it should be a string as with ljust c.s.)
-def zfill(x, width):
-    """zfill(x, width) -> string
-
-    Pad a numeric string x with zeros on the left, to fill a field
-    of the specified width.  The string x is never truncated.
-
-    """
-    if not isinstance(x, basestring):
-        x = repr(x)
-    return x.zfill(width)
-
-# Expand tabs in a string.
-# Doesn't take non-printing chars into account, but does understand \n.
-def expandtabs(s, tabsize=8):
-    """expandtabs(s [,tabsize]) -> string
-
-    Return a copy of the string s with all tab characters replaced
-    by the appropriate number of spaces, depending on the current
-    column, and the tabsize (default 8).
-
-    """
-    return s.expandtabs(tabsize)
-
-# Character translation through look-up table.
-def translate(s, table, deletions=""):
-    """translate(s,table [,deletions]) -> string
-
-    Return a copy of the string s, where all characters occurring
-    in the optional argument deletions are removed, and the
-    remaining characters have been mapped through the given
-    translation table, which must be a string of length 256.  The
-    deletions argument is not allowed for Unicode strings.
-
-    """
-    if deletions:
-        return s.translate(table, deletions)
-    else:
-        # Add s[:0] so that if s is Unicode and table is an 8-bit string,
-        # table is converted to Unicode.  This means that table *cannot*
-        # be a dictionary -- for that feature, use u.translate() directly.
-        return s.translate(table + s[:0])
-
-# Capitalize a string, e.g. "aBc  dEf" -> "Abc  def".
-def capitalize(s):
-    """capitalize(s) -> string
-
-    Return a copy of the string s with only its first character
-    capitalized.
-
-    """
-    return s.capitalize()
-
-# Substring replacement (global)
-def replace(s, old, new, maxsplit=-1):
-    """replace (str, old, new[, maxsplit]) -> string
-
-    Return a copy of string str with all occurrences of substring
-    old replaced by new. If the optional argument maxsplit is
-    given, only the first maxsplit occurrences are replaced.
-
-    """
-    return s.replace(old, new, maxsplit)
-
-
-# Try importing optional built-in module "strop" -- if it exists,
-# it redefines some string operations that are 100-1000 times faster.
-# It also defines values for whitespace, lowercase and uppercase
-# that match <ctype.h>'s definitions.
-
-try:
-    from strop import maketrans, lowercase, uppercase, whitespace
-    letters = lowercase + uppercase
-except ImportError:
-    pass                                          # Use the original versions
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.