Selaa lähdekoodia

[core] Add tidylib, a python wrapper for libtidy for HTML validation

bc Wong 13 vuotta sitten
vanhempi
commit
cdd1f980b2
36 muutettua tiedostoa jossa 4034 lisäystä ja 0 poistoa
  1. 2 0
      README.rst
  2. 19 0
      desktop/core/ext-py/pytidylib-0.2.1/LICENSE
  3. 12 0
      desktop/core/ext-py/pytidylib-0.2.1/MANIFEST.in
  4. 54 0
      desktop/core/ext-py/pytidylib-0.2.1/PKG-INFO
  5. 10 0
      desktop/core/ext-py/pytidylib-0.2.1/README
  6. 100 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_sources/index.txt
  7. 405 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/basic.css
  8. BIN
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/contents.png
  9. 210 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/default.css
  10. 232 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/doctools.js
  11. BIN
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/file.png
  12. 11 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/jquery.js
  13. BIN
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/minus.png
  14. BIN
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/navigation.png
  15. BIN
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/plus.png
  16. 61 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/pygments.css
  17. 16 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/rightsidebar.css
  18. 467 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/searchtools.js
  19. 557 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/sphinxdoc.css
  20. 19 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/stickysidebar.css
  21. 700 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/traditional.css
  22. 104 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/genindex.html
  23. 205 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/index.html
  24. 91 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/search.html
  25. 0 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/html/searchindex.js
  26. BIN
      desktop/core/ext-py/pytidylib-0.2.1/docs/pytidylib.pdf
  27. 26 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/rst/conf.py
  28. 100 0
      desktop/core/ext-py/pytidylib-0.2.1/docs/rst/index.rst
  29. 84 0
      desktop/core/ext-py/pytidylib-0.2.1/setup.py
  30. 81 0
      desktop/core/ext-py/pytidylib-0.2.1/tests/DocsTest.py
  31. 71 0
      desktop/core/ext-py/pytidylib-0.2.1/tests/FragsTest.py
  32. 41 0
      desktop/core/ext-py/pytidylib-0.2.1/tests/SinkMemTest.py
  33. 66 0
      desktop/core/ext-py/pytidylib-0.2.1/tests/threadsafety.py
  34. 188 0
      desktop/core/ext-py/pytidylib-0.2.1/tidylib/__init__.py
  35. 101 0
      desktop/core/ext-py/pytidylib-0.2.1/tidylib/sink.py
  36. 1 0
      ext/thirdparty/README.md

+ 2 - 0
README.rst

@@ -65,6 +65,7 @@ your system:
       * libmysqlclient-dev
       * libsasl2-dev
       * libsqlite3-dev
+      * libtidy (for unit tests only)
       * libxml2-dev
       * libxslt-dev
       * mvn (from ``maven2`` package or tarball)
@@ -79,6 +80,7 @@ your system:
       * gcc
       * gcc-c++
       * krb5-devel
+      * libtidy (for unit tests only)
       * libxml2-devel
       * libxslt-devel
       * mvn (from ``maven2`` package or tarball)

+ 19 - 0
desktop/core/ext-py/pytidylib-0.2.1/LICENSE

@@ -0,0 +1,19 @@
+Copyright 2009 Jason Stitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 12 - 0
desktop/core/ext-py/pytidylib-0.2.1/MANIFEST.in

@@ -0,0 +1,12 @@
+include README
+include LICENSE
+include MANIFEST.in
+include tidylib/*.py
+include tests/*.py
+include *.py
+include docs/pytidylib.pdf
+include docs/html/*.html
+include docs/html/*.js
+include docs/html/_static/*.*
+include docs/html/_sources/*.*
+include docs/rst/*.*

+ 54 - 0
desktop/core/ext-py/pytidylib-0.2.1/PKG-INFO

@@ -0,0 +1,54 @@
+Metadata-Version: 1.0
+Name: pytidylib
+Version: 0.2.1
+Summary: Python wrapper for HTML Tidy (tidylib)
+Home-page: http://countergram.com/open-source/pytidylib/
+Author: Jason Stitt
+Author-email: js@jasonstitt.com
+License: UNKNOWN
+Download-URL: http://cloud.github.com/downloads/countergram/pytidylib/pytidylib-0.2.1.tar.gz
+Description: 0.2.0: Works on Windows! See documentation for available DLL download
+        locations. Documentation rewritten and expanded.
+        
+        `PyTidyLib`_ is a Python package that wraps the `HTML Tidy`_ library. This
+        allows you, from Python code, to "fix" invalid (X)HTML markup. Some of the
+        library's many capabilities include:
+        
+        * Clean up unclosed tags and unescaped characters such as ampersands
+        * Output HTML 4 or XHTML, strict or transitional, and add missing doctypes
+        * Convert named entities to numeric entities, which can then be used in XML
+        documents without an HTML doctype.
+        * Clean up HTML from programs such as Word (to an extent)
+        * Indent the output, including proper (i.e. no) indenting for ``pre`` elements,
+        which some (X)HTML indenting code overlooks.
+        
+        Small example of use
+        ====================
+        
+        The following code cleans up an invalid HTML document and sets an option::
+        
+        from tidylib import tidy_document
+        document, errors = tidy_document('''<p>f&otilde;o <img src="bar.jpg">''',
+        options={'numeric-entities':1})
+        print document
+        print errors
+        
+        Docs
+        ====
+        
+        Documentation is shipped with the source distribution and is available at
+        the `PyTidyLib`_ web page.
+        
+        .. _`HTML Tidy`: http://tidy.sourceforge.net/
+        .. _`PyTidyLib`: http://countergram.com/open-source/pytidylib/
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Other Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Natural Language :: English
+Classifier: Topic :: Utilities
+Classifier: Topic :: Text Processing :: Markup :: HTML
+Classifier: Topic :: Text Processing :: Markup :: XML

+ 10 - 0
desktop/core/ext-py/pytidylib-0.2.1/README

@@ -0,0 +1,10 @@
+For documentation, see docs/html/index.html in this distribution, or
+http://countergram.com/open-source/pytidylib/
+
+Small example of use:
+
+from tidylib import tidy_document
+document, errors = tidy_document('''<p>f&otilde;o <img src="bar.jpg">''',
+    options={'numeric-entities':1})
+print document
+print errors

+ 100 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_sources/index.txt

@@ -0,0 +1,100 @@
+PyTidyLib: A Python Interface to HTML Tidy
+------------------------------------------
+
+`PyTidyLib`_ is a Python package that wraps the `HTML Tidy`_ library. This allows you, from Python code, to "fix" invalid (X)HTML markup. Some of the library's many capabilities include:
+
+* Clean up unclosed tags and unescaped characters such as ampersands
+* Output HTML 4 or XHTML, strict or transitional, and add missing doctypes
+* Convert named entities to numeric entities, which can then be used in XML documents without an HTML doctype.
+* Clean up HTML from programs such as Word (to an extent)
+* Indent the output, including proper (i.e. no) indenting for ``pre`` elements, which some (X)HTML indenting code overlooks.
+
+PyTidyLib is intended as as replacement for uTidyLib, which fills a similar purpose. The author previously used uTidyLib but found several areas for improvement, including OS X support, 64-bit platform support, unicode support, fixing a memory leak, and better speed.
+
+Naming conventions
+==================
+
+`HTML Tidy`_ is a longstanding open-source library written in C that implements the actual functionality of cleaning up (X)HTML markup. It provides a shared library (``so``, ``dll``, or ``dylib``) that can variously be called ``tidy``, ``libtidy``, or ``tidylib``, as well as a command-line executable named ``tidy``. For clarity, this document will consistently refer to it by the project name, HTML Tidy.
+
+`PyTidyLib`_ is the name of the Python package discussed here. As this is the package name, ``easy_install pytidylib`` or ``pip install pytidylib`` is correct (they are case-insenstive). The *module* name is ``tidylib``, so ``import tidylib`` is correct in Python code. This document will consistently use the package name, PyTidyLib, outside of code examples.
+
+Installing HTML Tidy
+====================
+
+You must have both `HTML Tidy`_ and `PyTidyLib`_ installed in order to use the functionality described here. There is no affiliation between the two projects. The following briefly outlines what you must do to install HTML Tidy. See the `HTML Tidy`_ web site for more information.
+
+**Linux/BSD or similar:** First, try to use your distribution's package management system (``apt-get``, ``yum``, etc.) to install HTML Tidy. It might go under the name ``libtidy``, ``tidylib``, ``tidy``, or something similar. Otherwise see *Building from Source*, below.
+
+**OS X:** You may already have HTML Tidy installed. In the Terminal, run ``locate libtidy`` and see if you get any results, which should end in ``dylib``. Otherwise see *Building from Source*, below.
+
+**Windows:** (Use PyTidyLib version 0.2 or later!) Prebuilt HTML Tidy DLLs are available from at least two locations. The `int64.org Tidy Binaries`_ page provides binaries that were built in 2005, for both 32-bit and 64-bit Windows, against a patched version of the source. The `HTML Tidy`_ web site links to a DLL built in 2006, for 32-bit Windows only, using the vanilla source (scroll near the bottom to "Other Builds" -- use the one that reads "exe/lib/dll", *not* the "exe"-only version.)
+
+Once you have a DLL (which may be named ``tidy.dll``, ``libtidy.dll``, or ``tidylib.dll``), you must place it in a directory on your system path. If you are running Python from the command-line, placing the DLL in the present working directory will work, but this is unreliable otherwise (e.g. for server software).
+
+See the articles `How to set the path in Windows 2000/Windows XP <http://www.computerhope.com/issues/ch000549.htm>`_ (ComputerHope.com) and `Modify a Users Path in Windows Vista <http://www.question-defense.com/2009/06/22/modify-a-users-path-in-windows-vista-vista-path-environment-variable/>`_ (Question Defense) for more information on your system path.
+
+**Building from Source:** The HTML Tidy developers have chosen to make the source code downloadable *only* through CVS, and not from the web site. Use the following CVS checkout at the command line::
+
+    cvs -z3 -d:pserver:anonymous@tidy.cvs.sourceforge.net:/cvsroot/tidy co -P tidy
+    
+Then see the instructions packaged with the source code or on the `HTML Tidy`_ web site.
+
+Installing PyTidyLib
+====================
+
+PyTidyLib is available on the Python Package Index and may be installed in the usual ways if you have `pip`_ or `setuptools`_ installed::
+
+    pip install pytidylib
+    # or:
+    easy_install pytidylib
+    
+You can also download the latest source distribution from the `PyTidyLib`_ web site.
+
+Small example of use
+====================
+
+The following code cleans up an invalid HTML document and sets an option::
+
+    from tidylib import tidy_document
+    document, errors = tidy_document('''<p>f&otilde;o <img src="bar.jpg">''',
+        options={'numeric-entities':1})
+    print document
+    print errors
+    
+Configuration options
+=====================
+
+The Python interface allows you to pass options directly to HTML Tidy. For a complete list of options, see the `HTML Tidy Configuration Options Quick Reference`_ or, from the command line, run ``tidy -help-config``.
+
+.. _`HTML Tidy Configuration Options Quick Reference`: http://tidy.sourceforge.net/docs/quickref.html
+
+This module sets certain default options, as follows::
+
+    BASE_OPTIONS = {
+        "output-xhtml": 1,     # XHTML instead of HTML4
+        "indent": 1,           # Pretty; not too much of a performance hit
+        "tidy-mark": 0,        # No tidy meta tag in output
+        "wrap": 0,             # No wrapping
+        "alt-text": "",        # Help ensure validation
+        "doctype": 'strict',   # Little sense in transitional for tool-generated markup...
+        "force-output": 1,     # May not get what you expect but you will get something
+        }
+
+If you do not like these options to be set for you, do the following after importing ``tidylib``::
+
+    tidylib.BASE_OPTIONS = {}
+
+Function reference
+==================
+
+.. autofunction:: tidylib.tidy_document
+
+.. autofunction:: tidylib.tidy_fragment
+
+.. autofunction:: tidylib.release_tidy_doc
+
+.. _`HTML Tidy`: http://tidy.sourceforge.net/
+.. _`PyTidyLib`: http://countergram.com/open-source/pytidylib/
+.. _`int64.org Tidy Binaries`: http://int64.org/projects/tidy-binaries
+.. _`setuptools`: http://pypi.python.org/pypi/setuptools
+.. _`pip`: http://pypi.python.org/pypi/pip

+ 405 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/basic.css

@@ -0,0 +1,405 @@
+/**
+ * Sphinx stylesheet -- basic theme
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+    clear: both;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+    width: 100%;
+    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;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+    padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+    float: left;
+    width: 230px;
+    margin-left: -100%;
+    font-size: 90%;
+}
+
+div.sphinxsidebar ul {
+    list-style: none;
+}
+
+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 form {
+    margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+img {
+    border: 0;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+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;
+}
+
+/* -- 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%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+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;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+a.headerlink {
+    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;
+}
+
+div.body p.caption {
+    text-align: inherit;
+}
+
+div.body td {
+    text-align: left;
+}
+
+.field-list ul {
+    padding-left: 1em;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+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 {
+    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;
+}
+
+p.admonition-title {
+    margin: 0px 10px 5px 0px;
+    font-weight: bold;
+}
+
+div.body p.centered {
+    text-align: center;
+    margin-top: 25px;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+    border: 0;
+    border-collapse: collapse;
+}
+
+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;
+}
+
+th {
+    text-align: left;
+    padding-right: 5px;
+}
+
+/* -- other body styles ----------------------------------------------------- */
+
+dl {
+    margin-bottom: 15px;
+}
+
+dd p {
+    margin-top: 0px;
+}
+
+dd ul, dd table {
+    margin-bottom: 10px;
+}
+
+dd {
+    margin-top: 3px;
+    margin-bottom: 10px;
+    margin-left: 30px;
+}
+
+dt:target, .highlight {
+    background-color: #fbe54e;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+.refcount {
+    color: #060;
+}
+
+.optional {
+    font-size: 1.3em;
+}
+
+.versionmodified {
+    font-style: italic;
+}
+
+.system-message {
+    background-color: #fda;
+    padding: 5px;
+    border: 3px solid red;
+}
+
+.footnote:target  {
+    background-color: #ffa
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+    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.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;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+    background-color: transparent;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+    vertical-align: middle;
+}
+
+div.body div.math p {
+    text-align: center;
+}
+
+span.eqno {
+    float: right;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+    div.document,
+    div.documentwrapper,
+    div.bodywrapper {
+        margin: 0;
+        width: 100%;
+    }
+
+    div.sphinxsidebar,
+    div.related,
+    div.footer,
+    #top-link {
+        display: none;
+    }
+}

BIN
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/contents.png


+ 210 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/default.css

@@ -0,0 +1,210 @@
+/**
+ * Sphinx stylesheet -- default theme
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+    font-family: sans-serif;
+    font-size: 100%;
+    background-color: #11303d;
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+div.document {
+    background-color: #1c4e63;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+div.body {
+    background-color: #ffffff;
+    color: #000000;
+    padding: 0 20px 30px 20px;
+}
+
+div.footer {
+    color: #ffffff;
+    width: 100%;
+    padding: 9px 0 9px 0;
+    text-align: center;
+    font-size: 75%;
+}
+
+div.footer a {
+    color: #ffffff;
+    text-decoration: underline;
+}
+
+div.related {
+    background-color: #133f52;
+    line-height: 30px;
+    color: #ffffff;
+}
+
+div.related a {
+    color: #ffffff;
+}
+
+div.sphinxsidebar {
+}
+
+div.sphinxsidebar h3 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: #ffffff;
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+    color: #ffffff;
+}
+
+div.sphinxsidebar h4 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: #ffffff;
+    font-size: 1.3em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+}
+
+div.sphinxsidebar p {
+    color: #ffffff;
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    padding: 0;
+    color: #ffffff;
+}
+
+div.sphinxsidebar a {
+    color: #98dbcc;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+    color: #355f7c;
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: justify;
+    line-height: 130%;
+}
+
+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;
+}
+
+a.headerlink:hover {
+    background-color: #c60f0f;
+    color: white;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: justify;
+    line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+    display: inline;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+
+div.topic {
+    background-color: #eee;
+}
+
+div.warning {
+    background-color: #ffe4e4;
+    border: 1px solid #f66;
+}
+
+p.admonition-title {
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+pre {
+    padding: 5px;
+    background-color: #eeffcc;
+    color: #333333;
+    line-height: 120%;
+    border: 1px solid #ac9;
+    border-left: none;
+    border-right: none;
+}
+
+tt {
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}

+ 232 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/doctools.js

@@ -0,0 +1,232 @@
+/// XXX: make it cross browser
+
+/**
+ * make the code below compatible with browsers without
+ * an installed firebug like debugger
+ */
+if (!window.console || !console.firebug) {
+  var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
+      "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+  window.console = {};
+  for (var i = 0; i < names.length; ++i)
+    window.console[names[i]] = function() {}
+}
+
+/**
+ * small helper function to urldecode strings
+ */
+jQuery.urldecode = function(x) {
+  return decodeURIComponent(x).replace(/\+/g, ' ');
+}
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+  if (typeof s == 'undefined')
+    s = document.location.search;
+  var parts = s.substr(s.indexOf('?') + 1).split('&');
+  var result = {};
+  for (var i = 0; i < parts.length; i++) {
+    var tmp = parts[i].split('=', 2);
+    var key = jQuery.urldecode(tmp[0]);
+    var value = jQuery.urldecode(tmp[1]);
+    if (key in result)
+      result[key].push(value);
+    else
+      result[key] = [value];
+  }
+  return result;
+}
+
+/**
+ * small function to check if an array contains
+ * a given item.
+ */
+jQuery.contains = function(arr, item) {
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] == item)
+      return true;
+  }
+  return false;
+}
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+  function highlight(node) {
+    if (node.nodeType == 3) {
+      var val = node.nodeValue;
+      var pos = val.toLowerCase().indexOf(text);
+      if (pos >= 0 && !jQuery.className.has(node.parentNode, className)) {
+        var span = document.createElement("span");
+        span.className = className;
+        span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+        node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+          document.createTextNode(val.substr(pos + text.length)),
+          node.nextSibling));
+        node.nodeValue = val.substr(0, pos);
+      }
+    }
+    else if (!jQuery(node).is("button, select, textarea")) {
+      jQuery.each(node.childNodes, function() {
+        highlight(this)
+      });
+    }
+  }
+  return this.each(function() {
+    highlight(this);
+  });
+}
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+  init : function() {
+    this.fixFirefoxAnchorBug();
+    this.highlightSearchWords();
+    this.initModIndex();
+  },
+
+  /**
+   * i18n support
+   */
+  TRANSLATIONS : {},
+  PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
+  LOCALE : 'unknown',
+
+  // gettext and ngettext don't access this so that the functions
+  // can savely bound to a different name (_ = Documentation.gettext)
+  gettext : function(string) {
+    var translated = Documentation.TRANSLATIONS[string];
+    if (typeof translated == 'undefined')
+      return string;
+    return (typeof translated == 'string') ? translated : translated[0];
+  },
+
+  ngettext : function(singular, plural, n) {
+    var translated = Documentation.TRANSLATIONS[singular];
+    if (typeof translated == 'undefined')
+      return (n == 1) ? singular : plural;
+    return translated[Documentation.PLURALEXPR(n)];
+  },
+
+  addTranslations : function(catalog) {
+    for (var key in catalog.messages)
+      this.TRANSLATIONS[key] = catalog.messages[key];
+    this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
+    this.LOCALE = catalog.locale;
+  },
+
+  /**
+   * add context elements like header anchor links
+   */
+  addContextElements : function() {
+    $('div[id] > :header:first').each(function() {
+      $('<a class="headerlink">\u00B6</a>').
+      attr('href', '#' + this.id).
+      attr('title', _('Permalink to this headline')).
+      appendTo(this);
+    });
+    $('dt[id]').each(function() {
+      $('<a class="headerlink">\u00B6</a>').
+      attr('href', '#' + this.id).
+      attr('title', _('Permalink to this definition')).
+      appendTo(this);
+    });
+  },
+
+  /**
+   * workaround a firefox stupidity
+   */
+  fixFirefoxAnchorBug : function() {
+    if (document.location.hash && $.browser.mozilla)
+      window.setTimeout(function() {
+        document.location.href += '';
+      }, 10);
+  },
+
+  /**
+   * highlight the search words provided in the url in the text
+   */
+  highlightSearchWords : function() {
+    var params = $.getQueryParameters();
+    var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
+    if (terms.length) {
+      var body = $('div.body');
+      window.setTimeout(function() {
+        $.each(terms, function() {
+          body.highlightText(this.toLowerCase(), 'highlight');
+        });
+      }, 10);
+      $('<li class="highlight-link"><a href="javascript:Documentation.' +
+        'hideSearchWords()">' + _('Hide Search Matches') + '</a></li>')
+          .appendTo($('.sidebar .this-page-menu'));
+    }
+  },
+
+  /**
+   * init the modindex toggle buttons
+   */
+  initModIndex : function() {
+    var togglers = $('img.toggler').click(function() {
+      var src = $(this).attr('src');
+      var idnum = $(this).attr('id').substr(7);
+      console.log($('tr.cg-' + idnum).toggle());
+      if (src.substr(-9) == 'minus.png')
+        $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
+      else
+        $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
+    }).css('display', '');
+    if (DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX) {
+        togglers.click();
+    }
+  },
+
+  /**
+   * helper function to hide the search marks again
+   */
+  hideSearchWords : function() {
+    $('.sidebar .this-page-menu li.highlight-link').fadeOut(300);
+    $('span.highlight').removeClass('highlight');
+  },
+
+  /**
+   * make the url absolute
+   */
+  makeURL : function(relativeURL) {
+    return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
+  },
+
+  /**
+   * get the current relative url
+   */
+  getCurrentURL : function() {
+    var path = document.location.pathname;
+    var parts = path.split(/\//);
+    $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
+      if (this == '..')
+        parts.pop();
+    });
+    var url = parts.join('/');
+    return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
+  }
+};
+
+// quick alias for translations
+_ = Documentation.gettext;
+
+$(document).ready(function() {
+  Documentation.init();
+});

BIN
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/file.png


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 11 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/jquery.js


BIN
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/minus.png


BIN
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/navigation.png


BIN
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/plus.png


+ 61 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/pygments.css

@@ -0,0 +1,61 @@
+.hll { background-color: #ffffcc }
+.c { color: #408090; font-style: italic } /* Comment */
+.err { border: 1px solid #FF0000 } /* Error */
+.k { color: #007020; font-weight: bold } /* Keyword */
+.o { color: #666666 } /* Operator */
+.cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.cp { color: #007020 } /* Comment.Preproc */
+.c1 { color: #408090; font-style: italic } /* Comment.Single */
+.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #00A000 } /* Generic.Inserted */
+.go { color: #303030 } /* Generic.Output */
+.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0040D0 } /* Generic.Traceback */
+.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
+.kp { color: #007020 } /* Keyword.Pseudo */
+.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #902000 } /* Keyword.Type */
+.m { color: #208050 } /* Literal.Number */
+.s { color: #4070a0 } /* Literal.String */
+.na { color: #4070a0 } /* Name.Attribute */
+.nb { color: #007020 } /* Name.Builtin */
+.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.no { color: #60add5 } /* Name.Constant */
+.nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.ne { color: #007020 } /* Name.Exception */
+.nf { color: #06287e } /* Name.Function */
+.nl { color: #002070; font-weight: bold } /* Name.Label */
+.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.nt { color: #062873; font-weight: bold } /* Name.Tag */
+.nv { color: #bb60d5 } /* Name.Variable */
+.ow { color: #007020; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mf { color: #208050 } /* Literal.Number.Float */
+.mh { color: #208050 } /* Literal.Number.Hex */
+.mi { color: #208050 } /* Literal.Number.Integer */
+.mo { color: #208050 } /* Literal.Number.Oct */
+.sb { color: #4070a0 } /* Literal.String.Backtick */
+.sc { color: #4070a0 } /* Literal.String.Char */
+.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #4070a0 } /* Literal.String.Double */
+.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.sh { color: #4070a0 } /* Literal.String.Heredoc */
+.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.sx { color: #c65d09 } /* Literal.String.Other */
+.sr { color: #235388 } /* Literal.String.Regex */
+.s1 { color: #4070a0 } /* Literal.String.Single */
+.ss { color: #517918 } /* Literal.String.Symbol */
+.bp { color: #007020 } /* Name.Builtin.Pseudo */
+.vc { color: #bb60d5 } /* Name.Variable.Class */
+.vg { color: #bb60d5 } /* Name.Variable.Global */
+.vi { color: #bb60d5 } /* Name.Variable.Instance */
+.il { color: #208050 } /* Literal.Number.Integer.Long */

+ 16 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/rightsidebar.css

@@ -0,0 +1,16 @@
+/**
+ * Sphinx Doc Design -- Right Side Bar Overrides
+ */
+
+
+div.sphinxsidebar {
+    float: right;
+}
+
+div.bodywrapper {
+    margin: 0 230px 0 0;
+}
+
+div.inlinecomments {
+    right: 250px;
+}

+ 467 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/searchtools.js

@@ -0,0 +1,467 @@
+/**
+ * helper function to return a node containing the
+ * search summary for a given text. keywords is a list
+ * of stemmed words, hlwords is the list of normal, unstemmed
+ * words. the first one is used to find the occurance, the
+ * latter for highlighting it.
+ */
+
+jQuery.makeSearchSummary = function(text, keywords, hlwords) {
+  var textLower = text.toLowerCase();
+  var start = 0;
+  $.each(keywords, function() {
+    var i = textLower.indexOf(this.toLowerCase());
+    if (i > -1)
+      start = i;
+  });
+  start = Math.max(start - 120, 0);
+  var excerpt = ((start > 0) ? '...' : '') +
+  $.trim(text.substr(start, 240)) +
+  ((start + 240 - text.length) ? '...' : '');
+  var rv = $('<div class="context"></div>').text(excerpt);
+  $.each(hlwords, function() {
+    rv = rv.highlightText(this, 'highlight');
+  });
+  return rv;
+}
+
+/**
+ * Porter Stemmer
+ */
+var PorterStemmer = function() {
+
+  var step2list = {
+    ational: 'ate',
+    tional: 'tion',
+    enci: 'ence',
+    anci: 'ance',
+    izer: 'ize',
+    bli: 'ble',
+    alli: 'al',
+    entli: 'ent',
+    eli: 'e',
+    ousli: 'ous',
+    ization: 'ize',
+    ation: 'ate',
+    ator: 'ate',
+    alism: 'al',
+    iveness: 'ive',
+    fulness: 'ful',
+    ousness: 'ous',
+    aliti: 'al',
+    iviti: 'ive',
+    biliti: 'ble',
+    logi: 'log'
+  };
+
+  var step3list = {
+    icate: 'ic',
+    ative: '',
+    alize: 'al',
+    iciti: 'ic',
+    ical: 'ic',
+    ful: '',
+    ness: ''
+  };
+
+  var c = "[^aeiou]";          // consonant
+  var v = "[aeiouy]";          // vowel
+  var C = c + "[^aeiouy]*";    // consonant sequence
+  var V = v + "[aeiou]*";      // vowel sequence
+
+  var mgr0 = "^(" + C + ")?" + V + C;                      // [C]VC... is m>0
+  var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$";    // [C]VC[V] is m=1
+  var mgr1 = "^(" + C + ")?" + V + C + V + C;              // [C]VCVC... is m>1
+  var s_v   = "^(" + C + ")?" + v;                         // vowel in stem
+
+  this.stemWord = function (w) {
+    var stem;
+    var suffix;
+    var firstch;
+    var origword = w;
+
+    if (w.length < 3)
+      return w;
+
+    var re;
+    var re2;
+    var re3;
+    var re4;
+
+    firstch = w.substr(0,1);
+    if (firstch == "y")
+      w = firstch.toUpperCase() + w.substr(1);
+
+    // Step 1a
+    re = /^(.+?)(ss|i)es$/;
+    re2 = /^(.+?)([^s])s$/;
+
+    if (re.test(w))
+      w = w.replace(re,"$1$2");
+    else if (re2.test(w))
+      w = w.replace(re2,"$1$2");
+
+    // Step 1b
+    re = /^(.+?)eed$/;
+    re2 = /^(.+?)(ed|ing)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      re = new RegExp(mgr0);
+      if (re.test(fp[1])) {
+        re = /.$/;
+        w = w.replace(re,"");
+      }
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1];
+      re2 = new RegExp(s_v);
+      if (re2.test(stem)) {
+        w = stem;
+        re2 = /(at|bl|iz)$/;
+        re3 = new RegExp("([^aeiouylsz])\\1$");
+        re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+        if (re2.test(w))
+          w = w + "e";
+        else if (re3.test(w)) {
+          re = /.$/;
+          w = w.replace(re,"");
+        }
+        else if (re4.test(w))
+          w = w + "e";
+      }
+    }
+
+    // Step 1c
+    re = /^(.+?)y$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(s_v);
+      if (re.test(stem))
+        w = stem + "i";
+    }
+
+    // Step 2
+    re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step2list[suffix];
+    }
+
+    // Step 3
+    re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step3list[suffix];
+    }
+
+    // Step 4
+    re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+    re2 = /^(.+?)(s|t)(ion)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      if (re.test(stem))
+        w = stem;
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1] + fp[2];
+      re2 = new RegExp(mgr1);
+      if (re2.test(stem))
+        w = stem;
+    }
+
+    // Step 5
+    re = /^(.+?)e$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      re2 = new RegExp(meq1);
+      re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+      if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
+        w = stem;
+    }
+    re = /ll$/;
+    re2 = new RegExp(mgr1);
+    if (re.test(w) && re2.test(w)) {
+      re = /.$/;
+      w = w.replace(re,"");
+    }
+
+    // and turn initial Y back to y
+    if (firstch == "y")
+      w = firstch.toLowerCase() + w.substr(1);
+    return w;
+  }
+}
+
+
+/**
+ * Search Module
+ */
+var Search = {
+
+  _index : null,
+  _queued_query : null,
+  _pulse_status : -1,
+
+  init : function() {
+      var params = $.getQueryParameters();
+      if (params.q) {
+          var query = params.q[0];
+          $('input[name="q"]')[0].value = query;
+          this.performSearch(query);
+      }
+  },
+
+  /**
+   * Sets the index
+   */
+  setIndex : function(index) {
+    var q;
+    this._index = index;
+    if ((q = this._queued_query) !== null) {
+      this._queued_query = null;
+      Search.query(q);
+    }
+  },
+
+  hasIndex : function() {
+      return this._index !== null;
+  },
+
+  deferQuery : function(query) {
+      this._queued_query = query;
+  },
+
+  stopPulse : function() {
+      this._pulse_status = 0;
+  },
+
+  startPulse : function() {
+    if (this._pulse_status >= 0)
+        return;
+    function pulse() {
+      Search._pulse_status = (Search._pulse_status + 1) % 4;
+      var dotString = '';
+      for (var i = 0; i < Search._pulse_status; i++)
+        dotString += '.';
+      Search.dots.text(dotString);
+      if (Search._pulse_status > -1)
+        window.setTimeout(pulse, 500);
+    };
+    pulse();
+  },
+
+  /**
+   * perform a search for something
+   */
+  performSearch : function(query) {
+    // create the required interface elements
+    this.out = $('#search-results');
+    this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
+    this.dots = $('<span></span>').appendTo(this.title);
+    this.status = $('<p style="display: none"></p>').appendTo(this.out);
+    this.output = $('<ul class="search"/>').appendTo(this.out);
+
+    $('#search-progress').text(_('Preparing search...'));
+    this.startPulse();
+
+    // index already loaded, the browser was quick!
+    if (this.hasIndex())
+      this.query(query);
+    else
+      this.deferQuery(query);
+  },
+
+  query : function(query) {
+    // stem the searchterms and add them to the
+    // correct list
+    var stemmer = new PorterStemmer();
+    var searchterms = [];
+    var excluded = [];
+    var hlterms = [];
+    var tmp = query.split(/\s+/);
+    var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null;
+    for (var i = 0; i < tmp.length; i++) {
+      // stem the word
+      var word = stemmer.stemWord(tmp[i]).toLowerCase();
+      // select the correct list
+      if (word[0] == '-') {
+        var toAppend = excluded;
+        word = word.substr(1);
+      }
+      else {
+        var toAppend = searchterms;
+        hlterms.push(tmp[i].toLowerCase());
+      }
+      // only add if not already in the list
+      if (!$.contains(toAppend, word))
+        toAppend.push(word);
+    };
+    var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
+
+    console.debug('SEARCH: searching for:');
+    console.info('required: ', searchterms);
+    console.info('excluded: ', excluded);
+
+    // prepare search
+    var filenames = this._index.filenames;
+    var titles = this._index.titles;
+    var terms = this._index.terms;
+    var descrefs = this._index.descrefs;
+    var modules = this._index.modules;
+    var desctypes = this._index.desctypes;
+    var fileMap = {};
+    var files = null;
+    var objectResults = [];
+    var regularResults = [];
+    $('#search-progress').empty();
+
+    // lookup as object
+    if (object != null) {
+      for (var module in modules) {
+        if (module.indexOf(object) > -1) {
+          fn = modules[module];
+          descr = _('module, in ') + titles[fn];
+          objectResults.push([filenames[fn], module, '#module-'+module, descr]);
+        }
+      }
+      for (var prefix in descrefs) {
+        for (var name in descrefs[prefix]) {
+          var fullname = (prefix ? prefix + '.' : '') + name;
+          if (fullname.toLowerCase().indexOf(object) > -1) {
+            match = descrefs[prefix][name];
+            descr = desctypes[match[1]] + _(', in ') + titles[match[0]];
+            objectResults.push([filenames[match[0]], fullname, '#'+fullname, descr]);
+          }
+        }
+      }
+    }
+
+    // sort results descending
+    objectResults.sort(function(a, b) {
+      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+    });
+
+
+    // perform the search on the required terms
+    for (var i = 0; i < searchterms.length; i++) {
+      var word = searchterms[i];
+      // no match but word was a required one
+      if ((files = terms[word]) == null)
+        break;
+      if (files.length == undefined) {
+        files = [files];
+      }
+      // create the mapping
+      for (var j = 0; j < files.length; j++) {
+        var file = files[j];
+        if (file in fileMap)
+          fileMap[file].push(word);
+        else
+          fileMap[file] = [word];
+      }
+    }
+
+    // now check if the files don't contain excluded terms
+    for (var file in fileMap) {
+      var valid = true;
+
+      // check if all requirements are matched
+      if (fileMap[file].length != searchterms.length)
+        continue;
+
+      // ensure that none of the excluded terms is in the
+      // search result.
+      for (var i = 0; i < excluded.length; i++) {
+        if (terms[excluded[i]] == file ||
+            $.contains(terms[excluded[i]] || [], file)) {
+          valid = false;
+          break;
+        }
+      }
+
+      // if we have still a valid result we can add it
+      // to the result list
+      if (valid)
+        regularResults.push([filenames[file], titles[file], '', null]);
+    }
+
+    // delete unused variables in order to not waste
+    // memory until list is retrieved completely
+    delete filenames, titles, terms;
+
+    // now sort the regular results descending by title
+    regularResults.sort(function(a, b) {
+      var left = a[1].toLowerCase();
+      var right = b[1].toLowerCase();
+      return (left > right) ? -1 : ((left < right) ? 1 : 0);
+    });
+
+    // combine both
+    var results = regularResults.concat(objectResults);
+
+    // print the results
+    var resultCount = results.length;
+    function displayNextItem() {
+      // results left, load the summary and display it
+      if (results.length) {
+        var item = results.pop();
+        var listItem = $('<li style="display:none"></li>');
+        listItem.append($('<a/>').attr(
+          'href',
+          item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
+          highlightstring + item[2]).html(item[1]));
+        if (item[3]) {
+          listItem.append($('<span> (' + item[3] + ')</span>'));
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
+        } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
+          $.get('_sources/' + item[0] + '.txt', function(data) {
+            listItem.append($.makeSearchSummary(data, searchterms, hlterms));
+            Search.output.append(listItem);
+            listItem.slideDown(5, function() {
+              displayNextItem();
+            });
+          });
+        } else {
+          // no source available, just display title
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
+        }
+      }
+      // search finished, update title and status message
+      else {
+        Search.stopPulse();
+        Search.title.text(_('Search Results'));
+        if (!resultCount)
+          Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
+        else
+            Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
+        Search.status.fadeIn(500);
+      }
+    }
+    displayNextItem();
+  }
+}
+
+$(document).ready(function() {
+  Search.init();
+});

+ 557 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/sphinxdoc.css

@@ -0,0 +1,557 @@
+/**
+ * Alternate Sphinx design
+ * Originally created by Armin Ronacher for Werkzeug, adapted by Georg Brandl.
+ */
+
+body {
+    font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif;
+    font-size: 14px;
+    letter-spacing: -0.01em;
+    line-height: 150%;
+    text-align: center;
+    /*background-color: #AFC1C4; */
+    background-color: #BFD1D4;
+    color: black;
+    padding: 0;
+    border: 1px solid #aaa;
+
+    margin: 0px 80px 0px 80px;
+    min-width: 740px;
+}
+
+a {
+    color: #CA7900;
+    text-decoration: none;
+}
+
+a:hover {
+    color: #2491CF;
+}
+
+pre {
+    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.95em;
+    letter-spacing: 0.015em;
+    padding: 0.5em;
+    border: 1px solid #ccc;
+    background-color: #f8f8f8;
+}
+
+td.linenos pre {
+    padding: 0.5em 0;
+    border: 0;
+    background-color: transparent;
+    color: #aaa;
+}
+
+table.highlighttable {
+    margin-left: 0.5em;
+}
+
+table.highlighttable td {
+    padding: 0 0.5em 0 0.5em;
+}
+
+cite, code, tt {
+    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.95em;
+    letter-spacing: 0.01em;
+}
+
+hr {
+    border: 1px solid #abc;
+    margin: 2em;
+}
+
+tt {
+    background-color: #f2f2f2;
+    border-bottom: 1px solid #ddd;
+    color: #333;
+}
+
+tt.descname {
+    background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+    border: 0;
+}
+
+tt.descclassname {
+    background-color: transparent;
+    border: 0;
+}
+
+tt.xref {
+    background-color: transparent;
+    font-weight: bold;
+    border: 0;
+}
+
+a tt {
+    background-color: transparent;
+    font-weight: bold;
+    border: 0;
+    color: #CA7900;
+}
+
+a tt:hover {
+    color: #2491CF;
+}
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+dl {
+    margin-bottom: 15px;
+}
+
+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;
+}
+
+pre {
+    line-height: 120%;
+}
+
+pre a {
+    color: inherit;
+    text-decoration: underline;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+div.document {
+    background-color: white;
+    text-align: left;
+    background-image: url(contents.png);
+    background-repeat: repeat-x;
+}
+
+/*
+div.documentwrapper {
+    width: 100%;
+}
+*/
+
+div.clearer {
+    clear: both;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+    background-image: url(navigation.png);
+    height: 2em;
+    list-style: none;
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    margin: 0;
+    padding-left: 10px;
+}
+
+div.related ul li {
+    margin: 0;
+    padding: 0;
+    height: 2em;
+    float: left;
+}
+
+div.related ul li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+div.related ul li a {
+    margin: 0;
+    padding: 0 5px 0 5px;
+    line-height: 1.75em;
+    color: #EE9816;
+}
+
+div.related ul li a:hover {
+    color: #3CA8E7;
+}
+
+div.body {
+    margin: 0;
+    padding: 0.5em 20px 20px 20px;
+}
+
+div.bodywrapper {
+    margin: 0 240px 0 0;
+    border-right: 1px solid #ccc;
+}
+
+div.body a {
+    text-decoration: underline;
+}
+
+div.sphinxsidebar {
+    margin: 0;
+    padding: 0.5em 15px 15px 0;
+    width: 210px;
+    float: right;
+    text-align: left;
+/*    margin-left: -100%; */
+}
+
+div.sphinxsidebar h4, div.sphinxsidebar h3 {
+    margin: 1em 0 0.5em 0;
+    font-size: 0.9em;
+    padding: 0.1em 0 0.1em 0.5em;
+    color: white;
+    border: 1px solid #86989B;
+    background-color: #AFC1C4;
+}
+
+div.sphinxsidebar h3 a {
+    color: white;
+}
+
+div.sphinxsidebar ul {
+    padding-left: 1.5em;
+    margin-top: 7px;
+    list-style: none;
+    padding: 0;
+    line-height: 130%;
+}
+
+div.sphinxsidebar ul ul {
+    list-style: square;
+    margin-left: 20px;
+}
+
+p {
+    margin: 0.8em 0 0.5em 0;
+}
+
+p.rubric {
+    font-weight: bold;
+}
+
+div.sidebar {
+    margin: 0 0 0.5em 1em;
+    border: 1px solid #ddb;
+    padding: 7px 7px 0 7px;
+    background-color: #ffe;
+    width: 40%;
+    float: right;
+}
+
+div.quotebar {
+    background-color: #f8f8f8;
+    max-width: 250px;
+    float: right;
+    padding: 2px 7px;
+    border: 1px solid #ccc;
+}
+
+p.sidebar-title {
+    font-weight: bold;
+}
+
+div.topic {
+    background-color: #f8f8f8;
+    border: 1px solid #ccc;
+    padding: 7px 7px 0 7px;
+    margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+    font-size: 1.1em;
+    font-weight: bold;
+}
+
+h1 {
+    margin: 0;
+    padding: 0.7em 0 0.3em 0;
+    font-size: 1.5em;
+    color: #11557C;
+}
+
+h2 {
+    margin: 1.3em 0 0.2em 0;
+    font-size: 1.35em;
+    padding: 0;
+}
+
+h3 {
+    margin: 1em 0 -0.3em 0;
+    font-size: 1.2em;
+}
+
+div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
+    color: black!important;
+}
+
+h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
+    display: none;
+    margin: 0 0 0 0.3em;
+    padding: 0 0.2em 0 0.2em;
+    color: #aaa!important;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+    display: inline;
+}
+
+h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
+h5 a.anchor:hover, h6 a.anchor:hover {
+    color: #777;
+    background-color: #eee;
+}
+
+table {
+    border-collapse: collapse;
+    margin: 0 -0.5em 0 -0.5em;
+}
+
+table td, table th {
+    padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+div.footer {
+    background-color: #E3EFF1;
+    color: #86989B;
+    padding: 3px 8px 3px 0;
+    clear: both;
+    font-size: 0.8em;
+    text-align: right;
+}
+
+div.footer a {
+    color: #86989B;
+    text-decoration: underline;
+}
+
+div.pagination {
+    margin-top: 2em;
+    padding-top: 0.5em;
+    border-top: 1px solid black;
+    text-align: center;
+}
+
+div.sphinxsidebar ul.toc {
+    margin: 1em 0 1em 0;
+    padding: 0 0 0 0.5em;
+    list-style: none;
+}
+
+div.sphinxsidebar ul.toc li {
+    margin: 0.5em 0 0.5em 0;
+    font-size: 0.9em;
+    line-height: 130%;
+}
+
+div.sphinxsidebar ul.toc li p {
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar ul.toc ul {
+    margin: 0.2em 0 0.2em 0;
+    padding: 0 0 0 1.8em;
+}
+
+div.sphinxsidebar ul.toc ul li {
+    padding: 0;
+}
+
+div.admonition, div.warning {
+    font-size: 0.9em;
+    margin: 1em 0 0 0;
+    border: 1px solid #86989B;
+    background-color: #f7f7f7;
+}
+
+div.admonition p, div.warning p {
+    margin: 0.5em 1em 0.5em 1em;
+    padding: 0;
+}
+
+div.admonition pre, div.warning pre {
+    margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+    margin: 0;
+    padding: 0.1em 0 0.1em 0.5em;
+    color: white;
+    border-bottom: 1px solid #86989B;
+    font-weight: bold;
+    background-color: #AFC1C4;
+}
+
+div.warning {
+    border: 1px solid #940000;
+}
+
+div.warning p.admonition-title {
+    background-color: #CF0000;
+    border-bottom-color: #940000;
+}
+
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+    margin: 0.1em 0.5em 0.5em 3em;
+    padding: 0;
+}
+
+div.versioninfo {
+    margin: 1em 0 0 0;
+    border: 1px solid #ccc;
+    background-color: #DDEAF0;
+    padding: 8px;
+    line-height: 1.3em;
+    font-size: 0.9em;
+}
+
+
+a.headerlink {
+    color: #c60f0f!important;
+    font-size: 1em;
+    margin-left: 6px;
+    padding: 0 4px 0 4px;
+    text-decoration: none!important;
+    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: #ccc;
+    color: white!important;
+}
+
+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;
+}
+
+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%;
+}
+
+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;
+}
+
+img.math {
+    vertical-align: center;
+}
+
+div.math {
+    text-align: center;
+}
+
+span.eqno {
+    float: right;
+}
+
+img.logo {
+    border: 0;
+}

+ 19 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/stickysidebar.css

@@ -0,0 +1,19 @@
+/**
+ * Sphinx Doc Design -- Sticky sidebar Overrides
+ */
+
+div.sphinxsidebar {
+    top: 30px;
+    left: 0px;
+    position: fixed;
+    margin: 0;
+    float: none;
+}
+
+div.related {
+    position: fixed;
+}
+
+div.documentwrapper {
+    margin-top: 30px;
+}

+ 700 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/_static/traditional.css

@@ -0,0 +1,700 @@
+/**
+ * Sphinx Doc Design -- traditional python.org style
+ */
+
+body {
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+/* :::: LAYOUT :::: */
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 230px 0 0;
+}
+
+div.body {
+    background-color: white;
+    padding: 0 20px 30px 20px;
+}
+
+div.sphinxsidebarwrapper {
+    border: 1px solid #99ccff;
+    padding: 10px;
+    margin: 10px 15px 10px 0;
+}
+
+div.sphinxsidebar {
+    float: right;
+    margin-left: -100%;
+    width: 230px;
+}
+
+div.clearer {
+    clear: both;
+}
+
+div.footer {
+    clear: both;
+    width: 100%;
+    background-color: #99ccff;
+    padding: 9px 0 9px 0;
+    text-align: center;
+}
+
+div.related {
+    background-color: #99ccff;
+    color: #333;
+    width: 100%;
+    height: 30px;
+    line-height: 30px;
+    border-bottom: 5px solid white;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+    margin: 0;
+    padding: 0 0 0 10px;
+    list-style: none;
+}
+
+div.related li {
+    display: inline;
+    font-weight: bold;
+}
+
+div.related li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+/* ::: SIDEBAR :::: */
+div.sphinxsidebar h3 {
+    margin: 0;
+}
+
+div.sphinxsidebar h4 {
+    margin: 5px 0 0 0;
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    margin-left: 15px;
+    padding: 0;
+}
+
+div.sphinxsidebar ul ul {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+    margin-top: 10px;
+}
+
+
+/* :::: 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 {
+    border-top: 1px solid #aaa;
+    background-color: #ddd;
+    margin: 10px 0 0 -20px;
+    padding: 5px 0 5px 20px;
+}
+
+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;
+    /*border: 2px solid #05171e;
+    background-color: #092835;
+    color: white;*/
+    font-weight: bold;
+}
+
+/* :::: INLINE COMMENTS :::: */
+
+div.inlinecommentswrapper {
+    float: right;
+    max-width: 40%;
+}
+
+div.commentmarker {
+    float: right;
+    background-image: url(style/comment.png);
+    background-repeat: no-repeat;
+    width: 25px;
+    height: 25px;
+    text-align: center;
+    padding-top: 3px;
+}
+
+div.nocommentmarker {
+    float: right;
+    background-image: url(style/nocomment.png);
+    background-repeat: no-repeat;
+    width: 25px;
+    height: 25px;
+}
+
+div.inlinecomments {
+    margin-left: 10px;
+    margin-bottom: 5px;
+    background-color: #eee;
+    border: 1px solid #ccc;
+    padding: 5px;
+}
+
+div.inlinecomment {
+    border-top: 1px solid #ccc;
+    padding-top: 5px;
+    margin-top: 5px;
+}
+
+.inlinecomments p {
+    margin: 5px 0 5px 0;
+}
+
+.inlinecomments .head {
+    font-weight: bold;
+}
+
+.inlinecomments .meta {
+    font-style: italic;
+}
+
+
+/* :::: COMMENTS :::: */
+
+div#comments h3 {
+    border-top: 1px solid #aaa;
+    padding: 5px 20px 5px 20px;
+    margin: 20px -20px 20px -20px;
+    background-color: #ddd;
+}
+
+/*
+div#comments {
+    background-color: #ccc;
+    margin: 40px -20px -30px -20px;
+    padding: 0 0 1px 0;
+}
+
+div#comments h4 {
+    margin: 30px 0 20px 0;
+    background-color: #aaa;
+    border-bottom: 1px solid #09232e;
+    color: #333;
+}
+
+div#comments form {
+    display: block;
+    margin: 0 0 0 20px;
+}
+
+div#comments textarea {
+    width: 98%;
+    height: 160px;
+}
+
+div#comments div.help {
+    margin: 20px 20px 10px 0;
+    background-color: #ccc;
+    color: #333;
+}
+
+div#comments div.help p {
+    margin: 0;
+    padding: 0 0 10px 0;
+}
+
+div#comments input, div#comments textarea {
+    font-family: 'Bitstream Vera Sans', 'Arial', sans-serif;
+    font-size: 13px;
+    color: black;
+    background-color: #aaa;
+    border: 1px solid #092835;
+}
+
+div#comments input[type="reset"],
+div#comments input[type="submit"] {
+    cursor: pointer;
+    font-weight: bold;
+    padding: 2px;
+    margin: 5px 5px 5px 0;
+    background-color: #666;
+    color: white;
+}
+
+div#comments div.comment {
+    margin: 10px 10px 10px 20px;
+    padding: 10px;
+    border: 1px solid #0f3646;
+    background-color: #aaa;
+    color: #333;
+}
+
+div#comments div.comment p {
+    margin: 5px 0 5px 0;
+}
+
+div#comments div.comment p.meta {
+    font-style: italic;
+    color: #444;
+    text-align: right;
+    margin: -5px 0 -5px 0;
+}
+
+div#comments div.comment h4 {
+    margin: -10px -10px 5px -10px;
+    padding: 3px;
+    font-size: 15px;
+    background-color: #888;
+    color: white;
+    border: 0;
+}
+
+div#comments div.comment pre,
+div#comments div.comment tt {
+    background-color: #ddd;
+    color: #111;
+    border: none;
+}
+
+div#comments div.comment a {
+    color: #fff;
+    text-decoration: underline;
+}
+
+div#comments div.comment blockquote {
+    margin: 10px;
+    padding: 10px;
+    border-left: 1px solid #0f3646;
+    /*border: 1px solid #0f3646;
+    background-color: #071c25;*/
+}
+
+div#comments em.important {
+    color: #d00;
+    font-weight: bold;
+    font-style: normal;
+}*/
+
+/* :::: SUGGEST CHANGES :::: */
+div#suggest-changes-box input, div#suggest-changes-box textarea {
+    border: 1px solid #ccc;
+    background-color: white;
+    color: black;
+}
+
+div#suggest-changes-box textarea {
+    width: 99%;
+    height: 400px;
+}
+
+
+/* :::: PREVIEW :::: */
+div.preview {
+    background-image: url(style/preview.png);
+    padding: 0 20px 20px 20px;
+    margin-bottom: 30px;
+}
+
+
+/* :::: INDEX PAGE :::: */
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.5em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+}
+
+/* :::: GENINDEX 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;
+}
+
+/* :::: GLOBAL STYLES :::: */
+
+p.subhead {
+    font-weight: bold;
+    margin-top: 20px;
+}
+
+a:link:active           { color: #ff0000; }
+a:link:hover            { background-color: #bbeeff; }
+a:visited:hover         { background-color: #bbeeff; }
+a:visited               { color: #551a8b; }
+a:link                  { color: #0000bb; }
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: avantgarde, sans-serif;
+    font-weight: bold;
+}
+
+div.body h1 { font-size: 180%; }
+div.body h2 { font-size: 150%; }
+div.body h3 { font-size: 120%; }
+div.body h4 { font-size: 120%; }
+
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink {
+    color: #c60f0f;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+    visibility: hidden;
+}
+
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink {
+    visibility: visible;
+}
+
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover {
+    background-color: #c60f0f;
+    color: white;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: justify;
+}
+
+div.body td {
+    text-align: left;
+}
+
+ul.fakelist {
+    list-style: none;
+    margin: 10px 0 10px 20px;
+    padding: 0;
+}
+
+/* "Footnotes" heading */
+p.rubric {
+    margin-top: 30px;
+    font-weight: bold;
+}
+
+/* "Topics" */
+
+div.topic {
+    background-color: #eee;
+    border: 1px solid #ccc;
+    padding: 0 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 dd {
+    margin-bottom: 10px;
+}
+
+div.admonition dl {
+    margin-bottom: 0;
+}
+
+div.admonition 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: 0 8px 2px 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;
+}
+
+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;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+.refcount {
+    color: #060;
+}
+
+th {
+    text-align: left;
+    padding-right: 5px;
+}
+
+pre {
+    font-family: monospace;
+    padding: 5px;
+    color: #00008b;
+    border-left: none;
+    border-right: none;
+}
+
+tt {
+    font-family: monospace;
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+}
+
+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: 13px;
+}
+
+form.comment input[type="text"] {
+    width: 240px;
+}
+
+form.comment textarea {
+    width: 100%;
+    height: 200px;
+    margin-bottom: 10px;
+}
+
+/* :::: PRINT :::: */
+@media print {
+    div.documentwrapper {
+        width: 100%;
+    }
+
+    div.body {
+        margin: 0;
+    }
+
+    div.sphinxsidebar,
+    div.related,
+    div.footer,
+    div#comments div.new-comment-box,
+    #top-link {
+        display: none;
+    }
+}

+ 104 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/genindex.html

@@ -0,0 +1,104 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Index &mdash; pytidylib module</title>
+    <link rel="stylesheet" href="_static/default.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '',
+        COLLAPSE_MODINDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="pytidylib module" href="index.html" /> 
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="" title="General Index"
+             accesskey="I">index</a></li>
+        <li><a href="index.html">pytidylib module</a> &raquo;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+
+   <h1 id="index">Index</h1>
+
+   <a href="#R"><strong>R</strong></a> | <a href="#T"><strong>T</strong></a> 
+
+   <hr />
+
+   
+<h2 id="R">R</h2>
+<table width="100%" class="indextable"><tr><td width="33%" valign="top">
+<dl>
+
+<dt><a href="index.html#tidylib.release_tidy_doc">release_tidy_doc() (in module tidylib)</a></dt></dl></td><td width="33%" valign="top"><dl>
+</dl></td></tr></table>
+
+<h2 id="T">T</h2>
+<table width="100%" class="indextable"><tr><td width="33%" valign="top">
+<dl>
+
+<dt><a href="index.html#tidylib.tidy_document">tidy_document() (in module tidylib)</a></dt>
+<dt><a href="index.html#tidylib.tidy_fragment">tidy_fragment() (in module tidylib)</a></dt></dl></td><td width="33%" valign="top"><dl>
+</dl></td></tr></table>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+
+   
+
+          <div id="searchbox" style="display: none">
+            <h3>Quick search</h3>
+              <form class="search" action="search.html" method="get">
+                <input type="text" name="q" size="18" />
+                <input type="submit" value="Go" />
+                <input type="hidden" name="check_keywords" value="yes" />
+                <input type="hidden" name="area" value="default" />
+              </form>
+              <p class="searchtip" style="font-size: 90%">
+              Enter search terms or a module, class or function name.
+              </p>
+          </div>
+          <script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="" title="General Index"
+             >index</a></li>
+        <li><a href="index.html">pytidylib module</a> &raquo;</li> 
+      </ul>
+    </div>
+    <div class="footer">
+      &copy; Copyright 2009 Jason Stitt.
+      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.3.
+    </div>
+  </body>
+</html>

+ 205 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/index.html

@@ -0,0 +1,205 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>PyTidyLib: A Python Interface to HTML Tidy &mdash; pytidylib module</title>
+    <link rel="stylesheet" href="_static/default.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '',
+        COLLAPSE_MODINDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="pytidylib module" href="" /> 
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li><a href="">pytidylib module</a> &raquo;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  <div class="section" id="pytidylib-a-python-interface-to-html-tidy">
+<h1>PyTidyLib: A Python Interface to HTML Tidy<a class="headerlink" href="#pytidylib-a-python-interface-to-html-tidy" title="Permalink to this headline">¶</a></h1>
+<p><a class="reference external" href="http://countergram.com/open-source/pytidylib/">PyTidyLib</a> is a Python package that wraps the <a class="reference external" href="http://tidy.sourceforge.net/">HTML Tidy</a> library. This allows you, from Python code, to &#8220;fix&#8221; invalid (X)HTML markup. Some of the library&#8217;s many capabilities include:</p>
+<ul class="simple">
+<li>Clean up unclosed tags and unescaped characters such as ampersands</li>
+<li>Output HTML 4 or XHTML, strict or transitional, and add missing doctypes</li>
+<li>Convert named entities to numeric entities, which can then be used in XML documents without an HTML doctype.</li>
+<li>Clean up HTML from programs such as Word (to an extent)</li>
+<li>Indent the output, including proper (i.e. no) indenting for <tt class="docutils literal"><span class="pre">pre</span></tt> elements, which some (X)HTML indenting code overlooks.</li>
+</ul>
+<p>PyTidyLib is intended as as replacement for uTidyLib, which fills a similar purpose. The author previously used uTidyLib but found several areas for improvement, including OS X support, 64-bit platform support, unicode support, fixing a memory leak, and better speed.</p>
+<div class="section" id="naming-conventions">
+<h2>Naming conventions<a class="headerlink" href="#naming-conventions" title="Permalink to this headline">¶</a></h2>
+<p><a class="reference external" href="http://tidy.sourceforge.net/">HTML Tidy</a> is a longstanding open-source library written in C that implements the actual functionality of cleaning up (X)HTML markup. It provides a shared library (<tt class="docutils literal"><span class="pre">so</span></tt>, <tt class="docutils literal"><span class="pre">dll</span></tt>, or <tt class="docutils literal"><span class="pre">dylib</span></tt>) that can variously be called <tt class="docutils literal"><span class="pre">tidy</span></tt>, <tt class="docutils literal"><span class="pre">libtidy</span></tt>, or <tt class="docutils literal"><span class="pre">tidylib</span></tt>, as well as a command-line executable named <tt class="docutils literal"><span class="pre">tidy</span></tt>. For clarity, this document will consistently refer to it by the project name, HTML Tidy.</p>
+<p><a class="reference external" href="http://countergram.com/open-source/pytidylib/">PyTidyLib</a> is the name of the Python package discussed here. As this is the package name, <tt class="docutils literal"><span class="pre">easy_install</span> <span class="pre">pytidylib</span></tt> or <tt class="docutils literal"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">pytidylib</span></tt> is correct (they are case-insenstive). The <em>module</em> name is <tt class="docutils literal"><span class="pre">tidylib</span></tt>, so <tt class="docutils literal"><span class="pre">import</span> <span class="pre">tidylib</span></tt> is correct in Python code. This document will consistently use the package name, PyTidyLib, outside of code examples.</p>
+</div>
+<div class="section" id="installing-html-tidy">
+<h2>Installing HTML Tidy<a class="headerlink" href="#installing-html-tidy" title="Permalink to this headline">¶</a></h2>
+<p>You must have both <a class="reference external" href="http://tidy.sourceforge.net/">HTML Tidy</a> and <a class="reference external" href="http://countergram.com/open-source/pytidylib/">PyTidyLib</a> installed in order to use the functionality described here. There is no affiliation between the two projects. The following briefly outlines what you must do to install HTML Tidy. See the <a class="reference external" href="http://tidy.sourceforge.net/">HTML Tidy</a> web site for more information.</p>
+<p><strong>Linux/BSD or similar:</strong> First, try to use your distribution&#8217;s package management system (<tt class="docutils literal"><span class="pre">apt-get</span></tt>, <tt class="docutils literal"><span class="pre">yum</span></tt>, etc.) to install HTML Tidy. It might go under the name <tt class="docutils literal"><span class="pre">libtidy</span></tt>, <tt class="docutils literal"><span class="pre">tidylib</span></tt>, <tt class="docutils literal"><span class="pre">tidy</span></tt>, or something similar. Otherwise see <em>Building from Source</em>, below.</p>
+<p><strong>OS X:</strong> You may already have HTML Tidy installed. In the Terminal, run <tt class="docutils literal"><span class="pre">locate</span> <span class="pre">libtidy</span></tt> and see if you get any results, which should end in <tt class="docutils literal"><span class="pre">dylib</span></tt>. Otherwise see <em>Building from Source</em>, below.</p>
+<p><strong>Windows:</strong> (Use PyTidyLib version 0.2 or later!) Prebuilt HTML Tidy DLLs are available from at least two locations. The <a class="reference external" href="http://int64.org/projects/tidy-binaries">int64.org Tidy Binaries</a> page provides binaries that were built in 2005, for both 32-bit and 64-bit Windows, against a patched version of the source. The <a class="reference external" href="http://tidy.sourceforge.net/">HTML Tidy</a> web site links to a DLL built in 2006, for 32-bit Windows only, using the vanilla source (scroll near the bottom to &#8220;Other Builds&#8221; &#8211; use the one that reads &#8220;exe/lib/dll&#8221;, <em>not</em> the &#8220;exe&#8221;-only version.)</p>
+<p>Once you have a DLL (which may be named <tt class="docutils literal"><span class="pre">tidy.dll</span></tt>, <tt class="docutils literal"><span class="pre">libtidy.dll</span></tt>, or <tt class="docutils literal"><span class="pre">tidylib.dll</span></tt>), you must place it in a directory on your system path. If you are running Python from the command-line, placing the DLL in the present working directory will work, but this is unreliable otherwise (e.g. for server software).</p>
+<p>See the articles <a class="reference external" href="http://www.computerhope.com/issues/ch000549.htm">How to set the path in Windows 2000/Windows XP</a> (ComputerHope.com) and <a class="reference external" href="http://www.question-defense.com/2009/06/22/modify-a-users-path-in-windows-vista-vista-path-environment-variable/">Modify a Users Path in Windows Vista</a> (Question Defense) for more information on your system path.</p>
+<p><strong>Building from Source:</strong> The HTML Tidy developers have chosen to make the source code downloadable <em>only</em> through CVS, and not from the web site. Use the following CVS checkout at the command line:</p>
+<div class="highlight-python"><pre>cvs -z3 -d:pserver:anonymous@tidy.cvs.sourceforge.net:/cvsroot/tidy co -P tidy</pre>
+</div>
+<p>Then see the instructions packaged with the source code or on the <a class="reference external" href="http://tidy.sourceforge.net/">HTML Tidy</a> web site.</p>
+</div>
+<div class="section" id="installing-pytidylib">
+<h2>Installing PyTidyLib<a class="headerlink" href="#installing-pytidylib" title="Permalink to this headline">¶</a></h2>
+<p>PyTidyLib is available on the Python Package Index and may be installed in the usual ways if you have <a class="reference external" href="http://pypi.python.org/pypi/pip">pip</a> or <a class="reference external" href="http://pypi.python.org/pypi/setuptools">setuptools</a> installed:</p>
+<div class="highlight-python"><pre>pip install pytidylib
+# or:
+easy_install pytidylib</pre>
+</div>
+<p>You can also download the latest source distribution from the <a class="reference external" href="http://countergram.com/open-source/pytidylib/">PyTidyLib</a> web site.</p>
+</div>
+<div class="section" id="small-example-of-use">
+<h2>Small example of use<a class="headerlink" href="#small-example-of-use" title="Permalink to this headline">¶</a></h2>
+<p>The following code cleans up an invalid HTML document and sets an option:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">tidylib</span> <span class="kn">import</span> <span class="n">tidy_document</span>
+<span class="n">document</span><span class="p">,</span> <span class="n">errors</span> <span class="o">=</span> <span class="n">tidy_document</span><span class="p">(</span><span class="s">&#39;&#39;&#39;&lt;p&gt;f&amp;otilde;o &lt;img src=&quot;bar.jpg&quot;&gt;&#39;&#39;&#39;</span><span class="p">,</span>
+    <span class="n">options</span><span class="o">=</span><span class="p">{</span><span class="s">&#39;numeric-entities&#39;</span><span class="p">:</span><span class="mf">1</span><span class="p">})</span>
+<span class="k">print</span> <span class="n">document</span>
+<span class="k">print</span> <span class="n">errors</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="configuration-options">
+<h2>Configuration options<a class="headerlink" href="#configuration-options" title="Permalink to this headline">¶</a></h2>
+<p>The Python interface allows you to pass options directly to HTML Tidy. For a complete list of options, see the <a class="reference external" href="http://tidy.sourceforge.net/docs/quickref.html">HTML Tidy Configuration Options Quick Reference</a> or, from the command line, run <tt class="docutils literal"><span class="pre">tidy</span> <span class="pre">-help-config</span></tt>.</p>
+<p>This module sets certain default options, as follows:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">BASE_OPTIONS</span> <span class="o">=</span> <span class="p">{</span>
+    <span class="s">&quot;output-xhtml&quot;</span><span class="p">:</span> <span class="mf">1</span><span class="p">,</span>     <span class="c"># XHTML instead of HTML4</span>
+    <span class="s">&quot;indent&quot;</span><span class="p">:</span> <span class="mf">1</span><span class="p">,</span>           <span class="c"># Pretty; not too much of a performance hit</span>
+    <span class="s">&quot;tidy-mark&quot;</span><span class="p">:</span> <span class="mf">0</span><span class="p">,</span>        <span class="c"># No tidy meta tag in output</span>
+    <span class="s">&quot;wrap&quot;</span><span class="p">:</span> <span class="mf">0</span><span class="p">,</span>             <span class="c"># No wrapping</span>
+    <span class="s">&quot;alt-text&quot;</span><span class="p">:</span> <span class="s">&quot;&quot;</span><span class="p">,</span>        <span class="c"># Help ensure validation</span>
+    <span class="s">&quot;doctype&quot;</span><span class="p">:</span> <span class="s">&#39;strict&#39;</span><span class="p">,</span>   <span class="c"># Little sense in transitional for tool-generated markup...</span>
+    <span class="s">&quot;force-output&quot;</span><span class="p">:</span> <span class="mf">1</span><span class="p">,</span>     <span class="c"># May not get what you expect but you will get something</span>
+    <span class="p">}</span>
+</pre></div>
+</div>
+<p>If you do not like these options to be set for you, do the following after importing <tt class="docutils literal"><span class="pre">tidylib</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">tidylib</span><span class="o">.</span><span class="n">BASE_OPTIONS</span> <span class="o">=</span> <span class="p">{}</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="function-reference">
+<h2>Function reference<a class="headerlink" href="#function-reference" title="Permalink to this headline">¶</a></h2>
+<dl class="function">
+<dt id="tidylib.tidy_document">
+<tt class="descclassname">tidylib.</tt><tt class="descname">tidy_document</tt><big>(</big><em>text</em>, <em>options=None</em>, <em>keep_doc=False</em><big>)</big><a class="headerlink" href="#tidylib.tidy_document" title="Permalink to this definition">¶</a></dt>
+<dd><p>Run a string with markup through Tidy and return the entire document.</p>
+<p>text (str): The markup, which may be anything from an empty string to a
+complete XHTML document. Unicode values are supported; they will be
+encoded as utf-8, and tidylib&#8217;s output will be decoded back to a unicode
+object.</p>
+<p>options (dict): Options passed directly to tidylib; see the tidylib docs
+or run tidy -help-config from the command line.</p>
+<p>keep_doc (boolean): If True, store 1 document object per thread and re-use
+it, for a slight performance boost especially when tidying very large numbers
+of very short documents.</p>
+<p>-&gt; (str, str): The tidied markup [0] and warning/error messages[1].
+Warnings and errors are returned just as tidylib returns them.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="tidylib.tidy_fragment">
+<tt class="descclassname">tidylib.</tt><tt class="descname">tidy_fragment</tt><big>(</big><em>text</em>, <em>options=None</em>, <em>keep_doc=False</em><big>)</big><a class="headerlink" href="#tidylib.tidy_fragment" title="Permalink to this definition">¶</a></dt>
+<dd><p>Tidy a string with markup and return it without the rest of the document.
+Tidy normally returns a full XHTML document; this function returns only
+the contents of the &lt;body&gt; element and is meant to be used for snippets.
+Calling tidy_fragment on elements that don&#8217;t go in the &lt;body&gt;, like &lt;title&gt;,
+will produce odd behavior.</p>
+<p>Arguments and return value as tidy_document. Note that tidy will always
+complain about the lack of a doctype and &lt;title&gt; element in fragments,
+and these errors are not stripped out for you.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="tidylib.release_tidy_doc">
+<tt class="descclassname">tidylib.</tt><tt class="descname">release_tidy_doc</tt><big>(</big><big>)</big><a class="headerlink" href="#tidylib.release_tidy_doc" title="Permalink to this definition">¶</a></dt>
+<dd>Release the stored document object in the current thread. Only useful
+if you have called tidy_document or tidy_fragament with keep_doc=True.</dd></dl>
+
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <h3><a href="">Table Of Contents</a></h3>
+            <ul>
+<li><a class="reference external" href="">PyTidyLib: A Python Interface to HTML Tidy</a><ul>
+<li><a class="reference external" href="#naming-conventions">Naming conventions</a></li>
+<li><a class="reference external" href="#installing-html-tidy">Installing HTML Tidy</a></li>
+<li><a class="reference external" href="#installing-pytidylib">Installing PyTidyLib</a></li>
+<li><a class="reference external" href="#small-example-of-use">Small example of use</a></li>
+<li><a class="reference external" href="#configuration-options">Configuration options</a></li>
+<li><a class="reference external" href="#function-reference">Function reference</a></li>
+</ul>
+</li>
+</ul>
+
+            <h3>This Page</h3>
+            <ul class="this-page-menu">
+              <li><a href="_sources/index.txt"
+                     rel="nofollow">Show Source</a></li>
+            </ul>
+          <div id="searchbox" style="display: none">
+            <h3>Quick search</h3>
+              <form class="search" action="search.html" method="get">
+                <input type="text" name="q" size="18" />
+                <input type="submit" value="Go" />
+                <input type="hidden" name="check_keywords" value="yes" />
+                <input type="hidden" name="area" value="default" />
+              </form>
+              <p class="searchtip" style="font-size: 90%">
+              Enter search terms or a module, class or function name.
+              </p>
+          </div>
+          <script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li><a href="">pytidylib module</a> &raquo;</li> 
+      </ul>
+    </div>
+    <div class="footer">
+      &copy; Copyright 2009 Jason Stitt.
+      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.3.
+    </div>
+  </body>
+</html>

+ 91 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/search.html

@@ -0,0 +1,91 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Search &mdash; pytidylib module</title>
+    <link rel="stylesheet" href="_static/default.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '',
+        COLLAPSE_MODINDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <script type="text/javascript" src="_static/searchtools.js"></script>
+    <link rel="top" title="pytidylib module" href="index.html" /> 
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li><a href="index.html">pytidylib module</a> &raquo;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  <h1 id="search-documentation">Search</h1>
+  <div id="fallback" class="admonition warning">
+  <script type="text/javascript">$('#fallback').hide();</script>
+  <p>
+    Please activate JavaScript to enable the search
+    functionality.
+  </p>
+  </div>
+  <p>
+    From here you can search these documents. Enter your search
+    words into the box below and click "search". Note that the search
+    function will automatically search for all of the words. Pages
+    containing fewer words won't appear in the result list.
+  </p>
+  <form action="" method="get">
+    <input type="text" name="q" value="" />
+    <input type="submit" value="search" />
+    <span id="search-progress" style="padding-left: 10px"></span>
+  </form>
+  
+  <div id="search-results">
+  
+  </div>
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li><a href="index.html">pytidylib module</a> &raquo;</li> 
+      </ul>
+    </div>
+  
+    <div class="footer">
+      &copy; Copyright 2009 Jason Stitt.
+      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.3.
+    </div>
+  <script type="text/javascript" src="searchindex.js"></script>
+
+  </body>
+</html>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/html/searchindex.js


BIN
desktop/core/ext-py/pytidylib-0.2.1/docs/pytidylib.pdf


+ 26 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/rst/conf.py

@@ -0,0 +1,26 @@
+# Configuration file for Sphinx documentation tool
+
+extensions = ['sphinx.ext.autodoc']
+
+master_doc = "index"
+
+project = "pytidylib"
+copyright = "2009 Jason Stitt"
+version = "0.1"
+language = "en"
+
+html_title = "pytidylib module"
+
+latex_use_modindex = False
+
+latex_documents = [
+    (
+    master_doc,
+    'pytidylib.tex',
+    'PyTidyLib documentation',
+    'Jason Stitt',
+    'howto',
+    False,
+    )
+    ]
+

+ 100 - 0
desktop/core/ext-py/pytidylib-0.2.1/docs/rst/index.rst

@@ -0,0 +1,100 @@
+PyTidyLib: A Python Interface to HTML Tidy
+------------------------------------------
+
+`PyTidyLib`_ is a Python package that wraps the `HTML Tidy`_ library. This allows you, from Python code, to "fix" invalid (X)HTML markup. Some of the library's many capabilities include:
+
+* Clean up unclosed tags and unescaped characters such as ampersands
+* Output HTML 4 or XHTML, strict or transitional, and add missing doctypes
+* Convert named entities to numeric entities, which can then be used in XML documents without an HTML doctype.
+* Clean up HTML from programs such as Word (to an extent)
+* Indent the output, including proper (i.e. no) indenting for ``pre`` elements, which some (X)HTML indenting code overlooks.
+
+PyTidyLib is intended as as replacement for uTidyLib, which fills a similar purpose. The author previously used uTidyLib but found several areas for improvement, including OS X support, 64-bit platform support, unicode support, fixing a memory leak, and better speed.
+
+Naming conventions
+==================
+
+`HTML Tidy`_ is a longstanding open-source library written in C that implements the actual functionality of cleaning up (X)HTML markup. It provides a shared library (``so``, ``dll``, or ``dylib``) that can variously be called ``tidy``, ``libtidy``, or ``tidylib``, as well as a command-line executable named ``tidy``. For clarity, this document will consistently refer to it by the project name, HTML Tidy.
+
+`PyTidyLib`_ is the name of the Python package discussed here. As this is the package name, ``easy_install pytidylib`` or ``pip install pytidylib`` is correct (they are case-insenstive). The *module* name is ``tidylib``, so ``import tidylib`` is correct in Python code. This document will consistently use the package name, PyTidyLib, outside of code examples.
+
+Installing HTML Tidy
+====================
+
+You must have both `HTML Tidy`_ and `PyTidyLib`_ installed in order to use the functionality described here. There is no affiliation between the two projects. The following briefly outlines what you must do to install HTML Tidy. See the `HTML Tidy`_ web site for more information.
+
+**Linux/BSD or similar:** First, try to use your distribution's package management system (``apt-get``, ``yum``, etc.) to install HTML Tidy. It might go under the name ``libtidy``, ``tidylib``, ``tidy``, or something similar. Otherwise see *Building from Source*, below.
+
+**OS X:** You may already have HTML Tidy installed. In the Terminal, run ``locate libtidy`` and see if you get any results, which should end in ``dylib``. Otherwise see *Building from Source*, below.
+
+**Windows:** (Use PyTidyLib version 0.2 or later!) Prebuilt HTML Tidy DLLs are available from at least two locations. The `int64.org Tidy Binaries`_ page provides binaries that were built in 2005, for both 32-bit and 64-bit Windows, against a patched version of the source. The `HTML Tidy`_ web site links to a DLL built in 2006, for 32-bit Windows only, using the vanilla source (scroll near the bottom to "Other Builds" -- use the one that reads "exe/lib/dll", *not* the "exe"-only version.)
+
+Once you have a DLL (which may be named ``tidy.dll``, ``libtidy.dll``, or ``tidylib.dll``), you must place it in a directory on your system path. If you are running Python from the command-line, placing the DLL in the present working directory will work, but this is unreliable otherwise (e.g. for server software).
+
+See the articles `How to set the path in Windows 2000/Windows XP <http://www.computerhope.com/issues/ch000549.htm>`_ (ComputerHope.com) and `Modify a Users Path in Windows Vista <http://www.question-defense.com/2009/06/22/modify-a-users-path-in-windows-vista-vista-path-environment-variable/>`_ (Question Defense) for more information on your system path.
+
+**Building from Source:** The HTML Tidy developers have chosen to make the source code downloadable *only* through CVS, and not from the web site. Use the following CVS checkout at the command line::
+
+    cvs -z3 -d:pserver:anonymous@tidy.cvs.sourceforge.net:/cvsroot/tidy co -P tidy
+    
+Then see the instructions packaged with the source code or on the `HTML Tidy`_ web site.
+
+Installing PyTidyLib
+====================
+
+PyTidyLib is available on the Python Package Index and may be installed in the usual ways if you have `pip`_ or `setuptools`_ installed::
+
+    pip install pytidylib
+    # or:
+    easy_install pytidylib
+    
+You can also download the latest source distribution from the `PyTidyLib`_ web site.
+
+Small example of use
+====================
+
+The following code cleans up an invalid HTML document and sets an option::
+
+    from tidylib import tidy_document
+    document, errors = tidy_document('''<p>f&otilde;o <img src="bar.jpg">''',
+        options={'numeric-entities':1})
+    print document
+    print errors
+    
+Configuration options
+=====================
+
+The Python interface allows you to pass options directly to HTML Tidy. For a complete list of options, see the `HTML Tidy Configuration Options Quick Reference`_ or, from the command line, run ``tidy -help-config``.
+
+.. _`HTML Tidy Configuration Options Quick Reference`: http://tidy.sourceforge.net/docs/quickref.html
+
+This module sets certain default options, as follows::
+
+    BASE_OPTIONS = {
+        "output-xhtml": 1,     # XHTML instead of HTML4
+        "indent": 1,           # Pretty; not too much of a performance hit
+        "tidy-mark": 0,        # No tidy meta tag in output
+        "wrap": 0,             # No wrapping
+        "alt-text": "",        # Help ensure validation
+        "doctype": 'strict',   # Little sense in transitional for tool-generated markup...
+        "force-output": 1,     # May not get what you expect but you will get something
+        }
+
+If you do not like these options to be set for you, do the following after importing ``tidylib``::
+
+    tidylib.BASE_OPTIONS = {}
+
+Function reference
+==================
+
+.. autofunction:: tidylib.tidy_document
+
+.. autofunction:: tidylib.tidy_fragment
+
+.. autofunction:: tidylib.release_tidy_doc
+
+.. _`HTML Tidy`: http://tidy.sourceforge.net/
+.. _`PyTidyLib`: http://countergram.com/open-source/pytidylib/
+.. _`int64.org Tidy Binaries`: http://int64.org/projects/tidy-binaries
+.. _`setuptools`: http://pypi.python.org/pypi/setuptools
+.. _`pip`: http://pypi.python.org/pypi/pip

+ 84 - 0
desktop/core/ext-py/pytidylib-0.2.1/setup.py

@@ -0,0 +1,84 @@
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+from distutils.core import setup
+
+longdesc = """\
+0.2.0: Works on Windows! See documentation for available DLL download
+locations. Documentation rewritten and expanded.
+
+`PyTidyLib`_ is a Python package that wraps the `HTML Tidy`_ library. This
+allows you, from Python code, to "fix" invalid (X)HTML markup. Some of the
+library's many capabilities include:
+
+* Clean up unclosed tags and unescaped characters such as ampersands
+* Output HTML 4 or XHTML, strict or transitional, and add missing doctypes
+* Convert named entities to numeric entities, which can then be used in XML
+  documents without an HTML doctype.
+* Clean up HTML from programs such as Word (to an extent)
+* Indent the output, including proper (i.e. no) indenting for ``pre`` elements,
+  which some (X)HTML indenting code overlooks.
+
+Small example of use
+====================
+
+The following code cleans up an invalid HTML document and sets an option::
+
+    from tidylib import tidy_document
+    document, errors = tidy_document('''<p>f&otilde;o <img src="bar.jpg">''',
+      options={'numeric-entities':1})
+    print document
+    print errors
+    
+Docs
+====
+
+Documentation is shipped with the source distribution and is available at
+the `PyTidyLib`_ web page.
+
+.. _`HTML Tidy`: http://tidy.sourceforge.net/
+.. _`PyTidyLib`: http://countergram.com/open-source/pytidylib/
+"""
+
+VERSION = "0.2.1"
+
+setup(
+    name="pytidylib",
+    version=VERSION,
+    description="Python wrapper for HTML Tidy (tidylib)",
+    long_description=longdesc,
+    author="Jason Stitt",
+    author_email="js@jasonstitt.com",
+    url="http://countergram.com/open-source/pytidylib/",
+    download_url="http://cloud.github.com/downloads/countergram/pytidylib/pytidylib-%s.tar.gz" % VERSION,
+    packages=['tidylib'],
+    classifiers=[
+          'Development Status :: 4 - Beta',
+          'Environment :: Other Environment',
+          'Intended Audience :: Developers',
+          'License :: OSI Approved :: MIT License',
+          'Programming Language :: Python',
+          'Natural Language :: English',
+          'Topic :: Utilities',
+          'Topic :: Text Processing :: Markup :: HTML',
+          'Topic :: Text Processing :: Markup :: XML',
+          ],
+    )
+

+ 81 - 0
desktop/core/ext-py/pytidylib-0.2.1/tests/DocsTest.py

@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import unittest
+from tidylib import tidy_document
+
+DOC = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title></title>
+  </head>
+  <body>
+    %s
+  </body>
+</html>
+'''
+
+class TestDocs1(unittest.TestCase):
+    """ Test some sample documents """
+    
+    def test_doc_with_unclosed_tag(self):
+        h = "<p>hello"
+        expected = DOC % '''<p>
+      hello
+    </p>'''
+        doc, err = tidy_document(h)
+        self.assertEqual(doc, expected)
+        
+    def test_doc_with_incomplete_img_tag(self):
+        h = "<img src='foo'>"
+        expected = DOC % '''<img src='foo' alt="" />'''
+        doc, err = tidy_document(h)
+        self.assertEqual(doc, expected)
+        
+    def test_doc_with_entity(self):
+        h = "&eacute;"
+        expected = DOC % "&eacute;"
+        doc, err = tidy_document(h)
+        self.assertEqual(doc, expected)
+        
+        expected = DOC % "&#233;"
+        doc, err = tidy_document(h, {'numeric-entities':1})
+        self.assertEqual(doc, expected)
+    
+    def test_doc_with_unicode(self):
+        h = u"unicode string ß"
+        expected = unicode(DOC, 'utf-8') % h
+        doc, err = tidy_document(h)
+        self.assertEqual(doc, expected)
+        
+    def test_doc_with_unicode_subclass(self):
+        class MyUnicode(unicode):
+            pass
+        
+        h = MyUnicode(u"unicode string ß")
+        expected = unicode(DOC, 'utf-8') % h
+        doc, err = tidy_document(h)
+        self.assertEqual(doc, expected)
+        
+    
+if __name__ == '__main__':
+    unittest.main()

+ 71 - 0
desktop/core/ext-py/pytidylib-0.2.1/tests/FragsTest.py

@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import unittest
+from tidylib import tidy_fragment
+
+class TestFrags1(unittest.TestCase):
+    """ Test some sample fragment documents """
+    
+    def test_frag_with_unclosed_tag(self):
+        h = "<p>hello"
+        expected = '''<p>
+      hello
+    </p>'''
+        doc, err = tidy_fragment(h)
+        self.assertEqual(doc, expected)
+        
+    def test_frag_with_incomplete_img_tag(self):
+        h = "<img src='foo'>"
+        expected = '''<img src='foo' alt="" />'''
+        doc, err = tidy_fragment(h)
+        self.assertEqual(doc, expected)
+        
+    def test_frag_with_entity(self):
+        h = "&eacute;"
+        expected = "&eacute;"
+        doc, err = tidy_fragment(h)
+        self.assertEqual(doc, expected)
+        
+        expected = "&#233;"
+        doc, err = tidy_fragment(h, {'numeric-entities':1})
+        self.assertEqual(doc, expected)
+    
+    def test_frag_with_unicode(self):
+        h = u"unicode string ß"
+        expected = h
+        doc, err = tidy_fragment(h)
+        self.assertEqual(doc, expected)
+
+    def test_frag_with_unicode_subclass(self):
+        class MyUnicode(unicode):
+            pass
+
+        h = MyUnicode(u"unicode string ß")
+        expected = h
+        doc, err = tidy_fragment(h)
+        self.assertEqual(doc, expected)
+    
+if __name__ == '__main__':
+    unittest.main()
+
+
+

+ 41 - 0
desktop/core/ext-py/pytidylib-0.2.1/tests/SinkMemTest.py

@@ -0,0 +1,41 @@
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import unittest
+from tidylib import tidy_document, tidy_fragment, sink
+
+class TestSinkMemory(unittest.TestCase):
+    """ Make sure error sinks are cleared properly """
+    
+    def test_tidy_document(self):
+        h = "<p>hello"
+        for i in xrange(100):
+            doc, err = tidy_document(h)
+        self.assertEqual(sink.sinks, {})
+        
+    def test_tidy_fragment(self):
+        h = "<p>hello"
+        for i in xrange(100):
+            doc, err = tidy_fragment(h)
+        self.assertEqual(sink.sinks, {})
+        
+if __name__ == '__main__':
+    unittest.main()
+    

+ 66 - 0
desktop/core/ext-py/pytidylib-0.2.1/tests/threadsafety.py

@@ -0,0 +1,66 @@
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import threading
+from Queue import Queue
+from tidylib import tidy_document
+
+error_queue = Queue()
+
+DOC = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title></title>
+  </head>
+  <body>
+    hello, world
+  </body>
+</html>
+'''
+
+SAMPLE = "hello, world"
+
+NUM_THREADS = 100
+NUM_TRIES = 100
+
+class TidyingThread(threading.Thread):
+    def run(self):
+        for x in xrange(NUM_TRIES):
+            output, errors = tidy_document(SAMPLE, keep_doc=True)
+            if output != DOC:
+                error_queue.put(output)
+            
+def run_test():
+    threads = []
+    for i in xrange(NUM_THREADS):
+        t = TidyingThread()
+        threads.append(t)
+        t.start()
+    for t in threads:
+        t.join()
+            
+if __name__ == '__main__':
+    run_test()
+    if not error_queue.empty():
+        print "About %s errors out of %s" % (error_queue.qsize(), NUM_THREADS * NUM_TRIES)
+        print error_queue.get()
+    
+    

+ 188 - 0
desktop/core/ext-py/pytidylib-0.2.1/tidylib/__init__.py

@@ -0,0 +1,188 @@
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import ctypes
+import threading
+import re
+import platform
+from sink import create_sink, destroy_sink
+
+__all__ = ['tidy_document', 'tidy_fragment', 'release_tidy_doc']
+
+#----------------------------------------------------------------------------#
+# Constants
+
+LIB_NAMES = ['libtidy', 'libtidy.so', 'libtidy-0.99.so.0', 'cygtidy-0-99-0',
+             'tidylib', 'libtidy.dylib', 'tidy']
+ENOMEM = -12
+RE_BODY = re.compile(r"<body>[\r\n]*(.+?)</body>", re.S)
+BASE_OPTIONS = {
+    "output-xhtml": 1,     # XHTML instead of HTML4
+    "indent": 1,           # Pretty; not too much of a performance hit
+    "tidy-mark": 0,        # No tidy meta tag in output
+    "wrap": 0,             # No wrapping
+    "alt-text": "",        # Help ensure validation
+    "doctype": 'strict',   # Little sense in transitional for tool-generated markup...
+    "force-output": 1,     # May not get what you expect but you will get something
+    }
+    
+# Note: These are meant as sensible defaults. If you don't like these being
+# applied by default, just set tidylib.BASE_OPTIONS = {} after importing.
+# You can of course override any of these options when you call the
+# tidy_document() or tidy_fragment() function
+
+#----------------------------------------------------------------------------#
+# Globals
+
+tidy = None
+thread_local_doc = threading.local()
+
+# Fix for Windows b/c tidy uses stdcall on Windows
+if "Windows" == platform.system():
+    load_library = ctypes.windll.LoadLibrary
+else:
+    load_library = ctypes.cdll.LoadLibrary
+
+for name in LIB_NAMES:
+    try:
+        tidy = load_library(name)
+        break
+    except OSError:
+        pass
+        
+if tidy is None:
+    raise OSError("Could not load libtidy using any of these names: %s" % (",".join(LIB_NAMES)))
+
+tidy.tidyCreate.restype = ctypes.POINTER(ctypes.c_void_p) # Fix for 64-bit systems
+
+#----------------------------------------------------------------------------#
+# Functions
+
+def tidy_document(text, options=None, keep_doc=False):
+    """ Run a string with markup through HTML Tidy; return the corrected one.
+    
+    text (str): The markup, which may be anything from an empty string to a
+    complete (X)HTML document. Unicode values are supported; they will be
+    encoded as UTF-8, and HTML Tidy's output will be decoded back to a unicode
+    object.
+    
+    options (dict): Options passed directly to HTML Tidy; see the HTML Tidy docs
+    (http://tidy.sourceforge.net/docs/quickref.html) or run tidy -help-config
+    from the command line.    
+    
+    keep_doc (boolean): If True, store 1 document object per thread and re-use
+    it, for a slight performance boost especially when tidying very large numbers
+    of very short documents.
+    
+    returns (str, str): The tidied markup [0] and warning/error messages[1].
+    Warnings and errors are returned just as tidylib returns them.
+    """
+    global tidy, option_names
+    
+    # Unicode approach is to encode as string, then decode libtidy output
+    use_unicode = False
+    if isinstance(text, unicode):
+        use_unicode = True
+        text = text.encode('utf-8')
+    
+    # Manage thread-local storage of persistent document object
+    if keep_doc:
+        if not hasattr(thread_local_doc, 'doc'):
+            thread_local_doc.doc = tidy.tidyCreate()
+        doc = thread_local_doc.doc
+    else:
+        doc = tidy.tidyCreate()
+    
+    # This is where error messages are sent by libtidy
+    sink = create_sink()
+    tidy.tidySetErrorSink(doc, sink)
+    
+    try:
+        # Set options on the document
+        # If keep_doc=True, options will persist between calls, but they can
+        # be overridden, and the BASE_OPTIONS will be set each time
+        tidy_options = dict(BASE_OPTIONS)
+        if options:
+            tidy_options.update(options)
+        if use_unicode:
+            tidy_options['input-encoding'] = 'utf8'
+            tidy_options['output-encoding'] = 'utf8'
+        for key in tidy_options:
+            value = tidy_options[key]
+            key = key.replace('_', '-')
+            if value is None:
+                value = ''
+            tidy.tidyOptParseValue(doc, key, str(value))
+            error = str(sink)
+            if error:
+                raise ValueError("(tidylib) " + error)
+    
+        # The point of the whole thing
+        tidy.tidyParseString(doc, text)
+        tidy.tidyCleanAndRepair(doc)
+        
+        # Guess at buffer size; tidy returns ENOMEM if the buffer is too
+        # small and puts the required size into out_length
+        out_length = ctypes.c_int(8192)
+        out = ctypes.c_buffer(out_length.value)
+        if ENOMEM == tidy.tidySaveString(doc, out, ctypes.byref(out_length)):
+            out = ctypes.c_buffer(out_length.value)
+            tidy.tidySaveString(doc, out, ctypes.byref(out_length))
+            
+        document = out.value
+        if use_unicode:
+            document = document.decode('utf-8')
+        errors = str(sink)
+    finally:
+        destroy_sink(sink)
+        if not keep_doc:
+            tidy.tidyRelease(doc)
+
+    return (document, errors)
+    
+    
+def tidy_fragment(text, options=None, keep_doc=False):
+    """ Tidy a string with markup and return only the <body> contents.
+    
+    HTML Tidy normally returns a full (X)HTML document; this function returns only
+    the contents of the <body> element and is meant to be used for snippets.
+    Calling tidy_fragment on elements that don't go in the <body>, like <title>,
+    will produce incorrect behavior.
+    
+    Arguments and return value are the same as tidy_document. Note that HTML
+    Tidy will always complain about the lack of a doctype and <title> element
+    in fragments, and these errors are not stripped out for you. """
+    document, errors = tidy_document(text, options, keep_doc)
+    match = RE_BODY.search(document)
+    if match:
+        document = match.group(1).strip()
+        return (document, errors)
+    else:
+        raise ValueError("tidy_fragment failed to process text")
+    
+def release_tidy_doc():
+    """ Release the stored document object in the current thread. Only useful
+    if you have called tidy_document or tidy_fragament with keep_doc=True. """
+    if hasattr(thread_local_doc, 'doc'):
+        tidy.tidyRelease(thread_local_doc.doc)
+        del thread_local_doc.doc
+    
+#----------------------------------------------------------------------------#
+    

+ 101 - 0
desktop/core/ext-py/pytidylib-0.2.1/tidylib/sink.py

@@ -0,0 +1,101 @@
+# Copyright 2009 Jason Stitt
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import ctypes
+import sys
+import threading
+import platform
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO 
+
+__all__ = ['Sink', 'create_sink', 'destroy_sink']
+
+#----------------------------------------------------------------------------#
+# Globals
+
+sinks = {} # of int: Sink
+last_sink_id = 0
+sink_id_lock = threading.Lock()
+
+#----------------------------------------------------------------------------#
+# ctypes type definitions
+
+# Fix for Windows b/c tidy uses stdcall on Windows
+if "Windows" == platform.system():
+    functype = ctypes.WINFUNCTYPE
+else:
+    functype = ctypes.CFUNCTYPE
+
+PutByteType = functype(None, ctypes.c_int, ctypes.c_char)
+
+class TidyOutputSink(ctypes.Structure):
+    """ Mirrors the _TidyOutputSink structure in tidy.h """
+    _fields_ = [
+        ('sinkData', ctypes.c_void_p),
+        ('putByte', PutByteType)
+        ]
+        
+#----------------------------------------------------------------------------#
+# Python interface
+    
+class Sink(object):
+    """ Represent a buffer to which Tidy writes errors with a callback function """
+    def __init__(self, sink_id):
+        self.data = StringIO()
+        self.sink_id = sink_id
+        self.struct = TidyOutputSink()
+        self.struct.sinkData = ctypes.cast(
+            ctypes.pointer(ctypes.c_int(sink_id)), ctypes.c_void_p) # Windows fix
+        write_func = self.data.write # Avoid 2 attr accesses per byte
+        def put_byte(sink_id, byte):
+            # We don't need sink_id because we have a separate put_byte
+            # function for each sink
+            write_func(byte)
+        self.struct.putByte = PutByteType(put_byte)
+        self._as_parameter_ = ctypes.byref(self.struct)
+    
+    def __str__(self):
+        return self.data.getvalue()
+        
+def create_sink():
+    """ Return a new Sink with a numeric ID incremented in a threadsafe way """
+    global last_sink_id, sink_id_lock, sinks
+    sink_id_lock.acquire()
+    try:
+        this_sink_id = last_sink_id
+        last_sink_id = (last_sink_id + 1) % sys.maxint
+        # If you have more than maxint sinks open at a time, you're screwed
+    finally:
+        sink_id_lock.release()
+    sink = Sink(this_sink_id)
+    sinks[this_sink_id] = sink
+    return sink
+    
+def destroy_sink(sink):
+    """ Free a Sink object by eliminating the reference from the global map """
+    global sinks
+    del sinks[sink.sink_id]
+    del sink
+
+#----------------------------------------------------------------------------#
+

+ 1 - 0
ext/thirdparty/README.md

@@ -36,6 +36,7 @@ Checked-in third party dependencies
 |Y|python-daemon|1.5.1|Python|http://pypi.python.org/pypi/python-daemon/|
 |Y|Python-pam|0.1.3|MIT|http://atlee.ca/software/pam/dist/0.1.3|
 |Y|Python-paste|1.7.2|MIT|http://pythonpaste.org|
+|Y|pytidylib|0.2.1|MIT|http://cloud.github.com/downloads/countergram/pytidylib/pytidylib-0.2.1.tar.gz|
 |Y|PyYAML|3.09|MIT|http://pyyaml.org/wiki/PyYAML|
 |Y|Raphael|MIT|http://raphaeljs.com/index.html|
 |Y|Shakespeares Sonnets|?|Public Domain from Gutenberg|http://www.gutenberg.org/dirs/etext97/wssnt10.txt|

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä